1. 程式人生 > >java執行緒池原理(入門版)——看完還不懂我直播吃香

java執行緒池原理(入門版)——看完還不懂我直播吃香

網上關於java執行緒池的部落格,大多是直接分析ThreadPoolExecutor類的實現,但是他們就像是做中文翻譯一樣,但是很少有講到本質的東西。

這篇部落格從根本出發,看完可以自己實現一個簡單執行緒池。下面正式開始。

一、我們知道,用java建立一條新執行緒,可以這樣做:

new Thread(new Runnable() {
   @Override
    public void run() {
        System.out.println("我是新執行緒!");
    }
}).start();

當run()方法執行完畢,這條執行緒就終止了。

這種情況下,頻繁的建立和終止執行緒,會對效能造成一定的影響。所以,我們首先要對執行緒進行復用。 二、我們知道,java中執行緒只能在start()方法中開啟執行,當run()方法執行完成則執行緒釋放,那麼如何才能複用執行緒呢?

思考一分鐘不難得出,只要run()方法中是一個死迴圈,那麼該執行緒就不會被釋放,也就可以不斷被複用!如下程式碼所示。

new Thread(new Runnable() {
   @Override
    public void run() {
    	System.out.println("我是新執行緒!");
        while(true) {
			System.out.println("執行緒還活著!");
		}
    }
}).start();

以上程式碼就可以對執行緒進行復用。 三、我們再想一下,提交到執行緒池的需要是覆蓋了run()方法的Runnable物件,這些Runnable物件必須要存起來,然後上面那條還活著的執行緒會依次消費它們,這樣才真正達到複用的目的!

那麼這些Runnable物件被存放到哪裡呢?答案很簡單,可以把它們放入BlockingQueue,阻塞佇列中!

然後這條活著的執行緒從頭消費BlockingQueue,如下所示。

BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
   @Override
    public void run() {
    	System.out.println("我是新執行緒!");
        while(true) {
			Runnable r = queue.poll();
			if (r!=null) {
				// 此處執行run方法
				r.run();
			}
		}
    }
}).start();

四、上面只涉及到一條執行緒,而“執行緒池”一般要求多條可以複用的執行緒。其實本質是一樣的,只需要多條可以複用的執行緒共同消費BlockingQueue即可。

BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
   @Override
    public void run() {
    	System.out.println("我是新執行緒1!");
        while(true) {
			Runnable r = queue.poll();
			if (r!=null) {
				// 此處執行run方法
				r.run();
			}
		}
    }
}).start();

new Thread(new Runnable() {
   @Override
    public void run() {
    	System.out.println("我是新執行緒2!");
        while(true) {
			Runnable r = queue.poll();
			if (r!=null) {
				// 此處執行run方法
				r.run();
			}
		}
    }
}).start();

以上就是執行緒池的基本實現原理啦!

java的ThreadPoolExecutor類同樣是根據上面的原理進行拓展的。看完還不懂,我直播吃香!