先看一個圖來簡單了解一下線程池的工作流程

1.線程池創(chuàng)建的Thread對象,run方法會通過阻塞隊列的take方法獲取一個Runnable對象
2.當(dāng)需要向線程池提交任務(wù)時會調(diào)用阻塞隊列的offer方法向隊列的尾部添加任務(wù)。
3.當(dāng)Runnable對象的run方法執(zhí)行完畢以后,Thread中的run方法又循環(huán)的從阻塞隊列中獲取下一個Runnable對象繼續(xù)執(zhí)行。
這樣就實現(xiàn)了Thread對象的重復(fù)利用,也就減少了創(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í)行完所有的任務(wù)
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 {
//每個任務(wù)隨機(jī)延時1s以內(nèi)的時間以模擬線程的運(yùn)行
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í)行完成所有的任務(wù)
2.線程池中固定只允許同時執(zhí)行的數(shù)量為3個,所以必須前3個執(zhí)行完至少一個后面的等待線程才能執(zhí)行
3.因為線程是并發(fā)執(zhí)行的,所以順序是亂序的,如果想順序可以把newFixedThreadPool(3)改為1,或者使用newSingleThreadExecutor。