三、執行緒池知識點整理筆記

Hro發表於2018-11-26

5、執行緒池知識點整理

1)、執行緒池型別:
	newCachedThreadPool:建立一個可快取執行緒池,如果執行緒池長度超過處理需要,
	                     可靈活回收空閒執行緒,若無可回收,則新建執行緒;
	newFixedThreadPool:建立一個定長執行緒池,可控制執行緒最大併發數,
	                    超出的執行緒會在佇列中等待;
	newScheduledThreadPool:建立一個定長執行緒池,支援定時及週期性任務執行;
	newSingleThreadExecutor:建立一個單執行緒化的執行緒池,它只會用
	                         唯一的工作執行緒來執行任務,保證所有任務按照
	                         指定順序(FIFO, LIFO, 優先順序)執行。
	newSingleThreadScheduledExecutor:只有一個執行緒,用來排程執行將來的任務。
	
2)、執行緒池示例引數:
	new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, 
	TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
	a)、第一個引數:corePoolSize,核心執行緒數量,
	b)、第二個引數:int maximumPoolSize,執行緒池最大執行緒數
	c)、第三個引數:long keepAliveTime,表示執行緒沒有任務執行時最多保持多久時間會終止
	d)、第四個引數:TimeUnit unit,引數keepAliveTime的時間單位,有7種取值
	e)、第五個引數:workQueue,一個阻塞佇列,通過execute方法提交的runnable物件
	               會儲存在該佇列中
	其中阻塞佇列分為以下幾種:
		(1)、ArrayBlockingQueue:基於陣列結構的有界阻塞佇列,按FIFO排序任務
		(2)、LinkedBlockingQueue:基於連結串列結構的阻塞佇列,按FIFO排序任務,吞
		 吐量通常要高於ArrayBlockingQuene;是無界的,可以不指定佇列的大小,但是
		 預設是Integer.MAX_VALU。
		(3)、SynchronousQueue:一個不儲存元素的阻塞佇列,每個插入操作必須等到
		另一個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,吞吐量通常要高於(2);
		(4)、priorityBlockingQueue:具有優先順序的無界阻塞佇列;
	
3)、執行緒池的飽和策略
	當阻塞佇列滿了,且沒有空閒的工作執行緒,如果繼續提交任務,必須採取一種策略處理該任務,
	執行緒池提供了4種策略:
	a)、ThreadPoolExcutor.AbortPolicy()——直接丟擲異常,預設操作;
	b)、ThreadPoolExcutor.CallerRunsPolicy()——只用呼叫者所線上程來執行任務;
	c)、ThreadPoolExcutor.DiscardOldersPolicy()——丟棄佇列裡最近的一個任務,
	    並執行當前任務;
	d)、ThreadPoolExcutor.DiscardPolicy()——不處理,直接丟掉;
	    也可以根據應用場景實現RejectedExecutionHandler介面,自定義飽和策略。
	
4)、執行流程:
	執行excute()方法之後
	a)、判斷執行緒池存在核心執行緒的數量與corePoolSize的大小,
	    若小於corePoolSize,則呼叫addWorker函式建立新執行緒;
	    否則執行b;
	b)、判斷等待佇列是否已滿,若未滿,則加入佇列中;否則執行c;
	c)、判斷執行緒池是否已滿,若未滿,則建立執行緒執行任務;否則執行d;
	d)、按照飽和策略,處理任務
部分原始碼(核心在addWorker):
        public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                   return;
                c = ctl.get();
                }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
                }
            else if (!addWorker(command, false))
                reject(command);
            }
複製程式碼

流程圖(網上找的):

三、執行緒池知識點整理筆記

相關文章