先看一個圖來簡單了解一下線程池的工作流程
1.線程池創(chuàng)建的Thread對象,run方法會通過阻塞隊列的take方法獲取一個Runnable對象
2.當需要向線程池提交任務時會調(diào)用阻塞隊列的offer方法向隊列的尾部添加任務悉盆。
3.當Runnable對象的run方法執(zhí)行完畢以后许起,Thread中的run方法又循環(huán)的從阻塞隊列中獲取下一個Runnable對象繼續(xù)執(zhí)行蹬耘。
這樣就實現(xiàn)了Thread對象的重復利用,也就減少了創(chuàng)建線程和銷毀線程所消耗的資源琐簇。
我們再看一個例子
public class MyClass {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);//線程池中,3工作線程
threadPool.execute(new ThreadPoolDemo.Task("a"));
threadPool.execute(new ThreadPoolDemo.Task("b"));
threadPool.execute(new ThreadPoolDemo.Task("c"));
threadPool.execute(new ThreadPoolDemo.Task("d"));
threadPool.execute(new ThreadPoolDemo.Task("e"));
threadPool.shutdown();
System.out.println(threadPool.isShutdown());//是否執(zhí)行了shutdown
System.out.println(threadPool.isTerminated());//是否執(zhí)行完所有的任務
while(!threadPool.isTerminated()){
//阻塞
}
System.out.println("OVER");
}
}
class ThreadPoolDemo {
static class Task implements Runnable {
private String id;
Task(String id) {
this.id = id;
}
@Override
public void run() {
System.out.println("Thread " + id + " is run");
try {
//每個任務隨機延時1s以內(nèi)的時間以模擬線程的運行
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread " + id + " run over");
}
}
}
執(zhí)行結(jié)果
Thread b is run
Thread a is run
Thread c is run
true
false
Thread c run over
Thread d is run
Thread b run over
Thread e is run
Thread e run over
Thread d run over
Thread a run over
OVER
我們可以看到:
1.打印的方法isShutdown 和 isTerminated 分別是true 和 false辩昆,isShutdown表示是否執(zhí)行了shutdown盲再,而isTerminated 指是否執(zhí)行完成所有的任務
2.線程池中固定只允許同時執(zhí)行的數(shù)量為3個,所以必須前3個執(zhí)行完至少一個后面的等待線程才能執(zhí)行
3.因為線程是并發(fā)執(zhí)行的棍鳖,所以順序是亂序的炮叶,如果想順序可以把newFixedThreadPool(3)改為1,或者使用newSingleThreadExecutor。