ThreadPoolExecutor中的任務提交和線程池中的線程複用

execute()方法

execute()傳一個Runnable接口,但是我們調用的時候傳的是一個實現了Runnable接口的類。多態特性由多態可知,子類對象賦給父類對象時其子類的run方法就傳給了父類對象的run方法

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        
        int c = ctl.get();
        //如果當前線程數小於,coresize,那麼我們就要生成一個新的Worker
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        
        //如果當前線程數大於coresize,則放到阻塞隊列中
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            //特殊的線程池,cached
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

1)線程池有一個預熱功能,當線程數小於coresize時,此時addWorker中會生成新的Worker,Worker的構造函數如下

        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            //傳來的Runnable接口
            this.firstTask = firstTask;
            //通過線程工廠,把this(當前Worker)指針傳給Thread,
            //newThread()方法的參數是Runnable接口,Worker實現了Runnable接口,因此把Worker的run方法傳過去了,多態的用法
            this.thread = getThreadFactory().newThread(this);
        }

2)當addWorker添加成功是,就會調用Worker對象中的thread屬性的start()方法

	    w = new Worker(firstTask);
	    final Thread t = w.thread;
	    t.start();

3)此時,start方法會調用worker的run方法,即runWorker()方法

 		w.firstTask = null;
	    w.unlock(); // allow interrupts
	    boolean completedAbruptly = true;
	    try {
	      while (task != null || (task = getTask()) != null) {
	            ....
	            }

當task不爲空,即說明有任務過來
當task爲空,task=getTask()不爲空,說明沒有任務過來,從阻塞隊列中能獲取到任務
getTask方法

	        for (;;) {
	            ....
	             Runnable r = timed ?
	                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
	                    workQueue.take();
	            if (r != null)
	                    return r;
	            ....
	        }

線程池總結
1)當剛提交任務的時候,如果小於coresize,就生成新的Worker()即Thread。
2)如果提交時,大於了coresize,那麼就放入WorkQueue的阻塞隊列中。當阻塞隊列有元素時,那麼之前生成的線程就可以進行復用了

線程複用情形
假設有一個線程池的coresize爲5,那麼假設5個線程工作狀態,此時有一個任務來了。則5個線程工作完成後,它們中只有一個線程能夠獲取這個任務,其餘線程由於在getTask()中沒有搶到任務,因此getTask就會一直處於自旋且不會返回。這樣就完成了線程的複用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章