線程併發學習
線程併發學習—-核心概念(轉載)
線程併發學習—-線程阻塞(sleep、wait、notifyAll、notify、join)
線程併發學習—-線程阻塞(synchronized)
線程併發學習—-線程阻塞(lock)
線程併發學習—-Thread、Runnable、Callable
線程併發學習—-隊列(Queue)
spring學習—-線程池
java中一些鎖概念整理(轉載)
線程簡介
線程狀態轉換圖(網上load)
線程狀態介紹
- 新建狀態(New):新創建了一個線程對象。
- 就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
- 運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。
阻塞的情況分三種:
(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。
java中多線程實現
繼承Thread
例子
//繼承Thread類
public class ThreadDemo extends Thread{
//實現Thread類run方法
@Override
public void run(){
System.out.println("這是線程的run方法");
}
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo();
//啓動線程,爲什麼是start 不是run見源碼
threadDemo.start();
}
}
實現Runnable
例子
public class RunnableDemo implements Runnable {
@Override
public void run() {
System.out.println("這是實現Runnable的run方法1");
}
public static void main(String[] args) {
//實現Runnable接口實現
new Thread(new RunnableDemo()).start();
//匿名內部類實現
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("這是實現Runnable的run方法2");
}
}).start();
}
}
實現Callable
例子
public class CallableDemo implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("這是Callable的call方法");
return "success";
}
public static void main(String[] args) throws Exception{
CallableDemo callableDemo = new CallableDemo();
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList(); //Future 相當於是用來存放Executor執行的結果的一種容器
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new CallableDemo()));
}
for (Future<String> fs : results) {
if (fs.isDone()) {
System.out.println(fs.get());
} else {
System.out.println("Future result is not yet complete");
}
}
exec.shutdown();
}
}
三種方式分析
繼承Thread實現簡單,但有侷限性java的類只能繼承一個父類(一般不會使用)
實現接口更靈活,避免繼承的侷限,可以實現多個接口
實現Runnable與Callable大體一樣,區別
- Runnable使用run()方法,Callable使用call()方法
- run方法沒有返回值,call方法有返回值
- run不能拋出受檢查異常 ,call可以拋出受檢查異常。如:ClassNotFoundException
Runnable通過Thread包裝實現 或者 FutureTask包裝實現
Callable一般通過ExecutorService包裝,本質是通過FutureTask實現
java線程類圖分析
ThreadPoolExecutor的execute方法參數只能爲Runnable
AbstractExecutorService的submit方法可以將Runnable和Callable包裝爲FutureTask,再調用execute方法
FutureTask實現RunnableFuture實現Runnable接口
ThreadPoolExecutor的execute方法,addWorker—》Worker—》默認使用DefaultThreadFactory—》new Thread—》執行start方法啓動線程,執行FutureTask的run方法
詳情見http://blog.csdn.net/eos2009/article/details/78617618的源碼 AbstractExecutorService
自己的理解:java線程的本質 Thread 的start創建線程,執行run方法實現
源碼
Thread
//Thread 實現Runnable接口
public class Thread implements Runnable {
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
//通過調用底層start0方法創建執行線程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
//操作系統底層函數
private native void start0();
FutureTask
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
//將runnable任務包裝爲callable 使其有返回值 使用Executors工具類
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
Executors
//
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
//底層實現使用Runnable接口run方法
task.run();
return result;
}
}