要想理解清楚java線程池實現原理,明白下面幾個問題就可以了:
成都創新互聯公司擁有10余年成都網站建設工作經驗,為各大企業提供做網站、成都網站建設服務,對于網頁設計、PC網站建設(電腦版網站建設)、成都APP應用開發、wap網站建設(手機版網站建設)、程序開發、網站優化(SEO優化)、微網站、國際域名空間等,憑借多年來在互聯網的打拼,我們在互聯網網站建設行業積累了很多網站制作、網站設計、網絡營銷經驗,集策劃、開發、設計、營銷、管理等網站化運作于一體,具備承接各種規模類型的網站建設項目的能力。
(1):線程池存在哪些狀態,這些狀態之間是如何進行切換的呢?
(2):線程池的種類有哪些?
(3):創建線程池需要哪些參數,這些參數的具體含義是什么?
(4):將任務添加到線程池之后運行流程?
(5):線程池是怎么做到重用線程的呢?
(6):線程池的關閉
首先回答第一個問題:線程池存在哪些狀態;
查看ThreadPoolExecutor源碼便知曉:
[java]?view plain?copy
//?runState?is?stored?in?the?high-order?bits
private?static?final?int?RUNNING????=?-1??COUNT_BITS;
private?static?final?int?SHUTDOWN???=??0??COUNT_BITS;
private?static?final?int?STOP???????=??1??COUNT_BITS;
private?static?final?int?TIDYING????=??2??COUNT_BITS;
private?static?final?int?TERMINATED?=??3??COUNT_BITS;
存在5種狀態:
1Running:可以接受新任務,同時也可以處理阻塞隊列里面的任務;
2Shutdown:不可以接受新任務,但是可以處理阻塞隊列里面的任務;
3Stop:不可以接受新任務,也不處理阻塞隊列里面的任務,同時還中斷正在處理的任務;
4Tidying:屬于過渡階段,在這個階段表示所有的任務已經執行結束了,當前線程池中是不存在有效的線程的,并且將要調用terminated方法;
5Terminated:終止狀態,這個狀態是在調用完terminated方法之后所處的狀態;
那么這5種狀態之間是如何進行轉換的呢?查看ThreadPoolExecutor源碼里面的注釋便可以知道啦:
[java]?view plain?copy
*?RUNNING?-?SHUTDOWN
*????On?invocation?of?shutdown(),?perhaps?implicitly?in?finalize()
*?(RUNNING?or?SHUTDOWN)?-?STOP
*????On?invocation?of?shutdownNow()
*?SHUTDOWN?-?TIDYING
*????When?both?queue?and?pool?are?empty
*?STOP?-?TIDYING
*????When?pool?is?empty
*?TIDYING?-?TERMINATED
*????When?the?terminated()?hook?method?has?completed
從上面可以看到,在調用shutdown方法的時候,線程池狀態會從Running轉換成Shutdown;在調用shutdownNow方法的時候,線程池狀態會從Running/Shutdown轉換成Stop;在阻塞隊列為空同時線程池為空的情況下,線程池狀態會從Shutdown轉換成Tidying;在線程池為空的情況下,線程池狀態會從Stop轉換成Tidying;當調用terminated方法之后,線程池狀態會從Tidying轉換成Terminate;
在明白了線程池的各個狀態以及狀態之間是怎么進行切換之后,我們來看看第二個問題,線程池的種類:
(1):CachedThreadPool:緩存線程池,該類線程池中線程的數量是不確定的,理論上可以達到Integer.MAX_VALUE個,這種線程池中的線程都是非核心線程,既然是非核心線程,那么就存在超時淘汰機制了,當里面的某個線程空閑時間超過了設定的超時時間的話,就會回收掉該線程;
(2):FixedThreadPool:固定線程池,這類線程池中是只存在核心線程的,對于核心線程來說,如果我們不設置allowCoreThreadTimeOut屬性的話是不存在超時淘汰機制的,這類線程池中的corePoolSize的大小是等于maximumPoolSize大小的,也就是說,如果線程池中的線程都處于活動狀態的話,如果有新任務到來,他是不會開辟新的工作線程來處理這些任務的,只能將這些任務放到阻塞隊列里面進行等到,直到有核心線程空閑為止;
(3):ScheduledThreadPool:任務線程池,這種線程池中核心線程的數量是固定的,而對于非核心線程的數量是不限制的,同時對于非核心線程是存在超時淘汰機制的,主要適用于執行定時任務或者周期性任務的場景;
(4):SingleThreadPool:單一線程池,線程池里面只有一個線程,同時也不存在非核心線程,感覺像是FixedThreadPool的特殊版本,他主要用于確保任務在同一線程中的順序執行,有點類似于進行同步吧;
接下來我們來看第三個問題,創建線程池需要哪些參數:
同樣查看ThreadPoolExecutor源碼,查看創建線程池的構造函數:
[java]?view plain?copy
public?ThreadPoolExecutor(int?corePoolSize,
int?maximumPoolSize,
long?keepAliveTime,
TimeUnit?unit,
BlockingQueueRunnable?workQueue,
ThreadFactory?threadFactory,
RejectedExecutionHandler?handler)
不管你調用的是ThreadPoolExecutor的哪個構造函數,最終都會執行到這個構造函數的,這個構造函數有7個參數,正是由于對這7個參數值的賦值不同,造成生成不同類型的線程池,比如我們常見的CachedThreadPoolExecutor、FixedThreadPoolExecutor
SingleThreadPoolExecutor、ScheduledThreadPoolExecutor,我們老看看這幾個參數的具體含義:
1corePoolSize:線程池中核心線程的數量;當提交一個任務到線程池的時候,線程池會創建一個線程來執行執行任務,即使有其他空閑的線程存在,直到線程數達到corePoolSize時不再創建,這時候會把提交的新任務放入到阻塞隊列中,如果調用了線程池的preStartAllCoreThreads方法,則會在創建線程池的時候初始化出來核心線程;
2maximumPoolSize:線程池允許創建的最大線程數;如果阻塞隊列已經滿了,同時已經創建的線程數小于最大線程數的話,那么會創建新的線程來處理阻塞隊列中的任務;
3keepAliveTime:線程活動保持時間,指的是工作線程空閑之后繼續存活的時間,默認情況下,這個參數只有線程數大于corePoolSize的時候才會起作用,即當線程池中的線程數目大于corePoolSize的時候,如果某一個線程的空閑時間達到keepAliveTime,那么這個線程是會被終止的,直到線程池中的線程數目不大于corePoolSize;如果調用allowCoreThreadTimeOut的話,在線程池中線程數量不大于corePoolSize的時候,keepAliveTime參數也可以起作用的,知道線程數目為0為止;
4unit:參數keepAliveTime的時間單位;
5workQueue:阻塞隊列;用于存儲等待執行的任務,有四種阻塞隊列類型,ArrayBlockingQueue(基于數組的有界阻塞隊列)、LinkedBlockingQueue(基于鏈表結構的阻塞隊列)、SynchronousQueue(不存儲元素的阻塞隊列)、PriorityBlockingQueue(具有優先級的阻塞隊列);
6threadFactory:用于創建線程的線程工廠;
7handler:當阻塞隊列滿了,且沒有空閑線程的情況下,也就是說這個時候,線程池中的線程數目已經達到了最大線程數量,處于飽和狀態,那么必須采取一種策略來處理新提交的任務,我們可以自己定義處理策略,也可以使用系統已經提供給我們的策略,先來看看系統為我們提供的4種策略,AbortPolicy(直接拋出異常)、CallerRunsPolicy(只有調用者所在的線程來運行任務)、DiscardOldestPolicy(丟棄阻塞隊列中最近的一個任務,并執行當前任務)、Discard(直接丟棄);
接下來就是將任務添加到線程池之后的運行流程了;
我們可以調用submit或者execute方法,兩者最大的區別在于,調用submit方法的話,我們可以傳入一個實現Callable接口的對象,進而能在當前任務執行結束之后通過Future對象獲得任務的返回值,submit內部實際上還是執行的execute方法;而調用execute方法的話,是不能獲得任務執行結束之后的返回值的;此外,調用submit方法的話是可以拋出異常的,但是調用execute方法的話,異常在其內部得到了消化,也就是說異常在其內部得到了處理,不會向外傳遞的;
因為submit方法最終也是會執行execute方法的,因此我們只需要了解execute方法就可以了:
在execute方法內部會分三種情況來進行處理:
1:首先判斷當前線程池中的線程數量是否小于corePoolSize,如果小于的話,則直接通過addWorker方法創建一個新的Worker對象來執行我們當前的任務;
2:如果說當前線程池中的線程數量大于corePoolSize的話,那么會嘗試將當前任務添加到阻塞隊列中,然后第二次檢查線程池的狀態,如果線程池不在Running狀態的話,會將剛剛添加到阻塞隊列中的任務移出,同時拒絕當前任務請求;如果第二次檢查發現當前線程池處于Running狀態的話,那么會查看當前線程池中的工作線程數量是否為0,如果為0的話,就會通過addWorker方法創建一個Worker對象出來處理阻塞隊列中的任務;
3:如果原先線程池就不處于Running狀態或者我們剛剛將當前任務添加到阻塞隊列的時候出現錯誤的話,那么會去嘗試通過addWorker創建新的Worker來處理當前任務,如果添加失敗的話,則拒絕當前任務請求;
可以看到在上面的execute方法中,我們僅僅只是檢查了當前線程池中的線程數量有沒有超過corePoolSize的情況,那么當前線程池中的線程數量有沒有超過maximumPoolSize是在哪里檢測的呢?實際上是在addWorker方法里面了,我們可以看下addWorker里面的一段代碼:
[java]?view plain?copy
if?(wc?=?CAPACITY?||
wc?=?(core???corePoolSize?:?maximumPoolSize))
return?false;
如果當前線程數量超過maximumPoolSize的話,直接就會調用return方法,返回false;
其實到這里我們很明顯可以知道,一個線程池中線程的數量實際上就是這個線程池中Worker的數量,如果Worker的大小超過了corePoolSize,那么任務都在阻塞隊列里面了,Worker是Java對我們任務的一個封裝類,他的聲明是醬紫的:
[java]?view plain?copy
private?final?class?Worker
extends?AbstractQueuedSynchronizer
implements?Runnable
可以看到他實現了Runnable接口,他是在addWorker方法里面通過new Worker(firstTask)創建的,我們來看看他的構造函數就知道了:
[java]?view plain?copy
Worker(Runnable?firstTask)?{
setState(-1);?//?inhibit?interrupts?until?runWorker
this.firstTask?=?firstTask;
this.thread?=?getThreadFactory().newThread(this);
}
而這里的firstTask其實就是我們調用execute或者submit的時候傳入的那個參數罷了,一般來說這些參數是實現Callable或者Runnable接口的;
在通過addWorker方法創建出來Worker對象之后,這個方法的最后會執行Worker內部thread屬性的start方法,而這個thread屬性實際上就是封裝了Worker的Thread,執行他的start方法實際上執行的是Worker的run方法,因為Worker是實現了Runnable接口的,在run方法里面就會執行runWorker方法,而runWorker方法里面首先會判斷當前我們傳入的任務是否為空,不為空的話直接就會執行我們通過execute或者submit方法提交的任務啦,注意一點就是我們雖然會通過submit方法提交實現了Callable接口的對象,但是在調用submit方法的時候,其實是會將Callable對象封裝成實現了Runnable接口對象的,不信我們看看submit方法源碼是怎么實現的:
[java]?view plain?copy
public?T?FutureT?submit(CallableT?task)?{
if?(task?==?null)?throw?new?NullPointerException();
RunnableFutureT?ftask?=?newTaskFor(task);
execute(ftask);
return?ftask;
}
看到沒有呢,實際上在你傳入實現了Callable接口對象的時候,在submit方法里面是會將其封裝成RunnableFuture對象的,而RunnableFuture接口是繼承了Runnable接口的;那么說白了其實就是直接執行我們提交任務的run方法了;如果為空的話,則會通過getTask方法從阻塞隊列里面拿出一個任務去執行;在任務執行結束之后繼續從阻塞隊列里面拿任務,直到getTask的返回值為空則退出runWorker內部循環,那么什么情況下getTask返回為空呢?查看getTask方法的源碼注釋可以知道:在Worker必須需要退出的情況下getTask會返回空,具體什么情況下Worker會退出呢?(1):當Worker的數量超過maximumPoolSize的時候;(2):當線程池狀態為Stop的時候;(3):當線程池狀態為Shutdown并且阻塞隊列為空的時候;(4):使用等待超時時間從阻塞隊列中拿數據,但是超時之后仍然沒有拿到數據;
如果runWorker方法退出了它里面的循環,那么就說明當前阻塞隊列里面是沒有任務可以執行的了,你可以看到在runWorker方法內部的finally語句塊中執行了processWorkerExit方法,用來對Worker對象進行回收操作,這個方法會傳入一個參數表示需要刪除的Worker對象;在進行Worker回收的時候會調用tryTerminate方法來嘗試關閉線程池,在tryTerminate方法里面會檢查是否有Worker在工作,檢查線程池的狀態,沒問題的話就會將當前線程池的狀態過渡到Tidying,之后調用terminated方法,將線程池狀態更新到Terminated;
從上面的分析中,我們可以看出線程池運行的4個階段:
(1):poolSize corePoolSize,則直接創建新的線程(核心線程)來執行當前提交的任務;
(2):poolSize = corePoolSize,并且此時阻塞隊列沒有滿,那么會將當前任務添加到阻塞隊列中,如果此時存在工作線程(非核心線程)的話,那么會由工作線程來處理該阻塞隊列中的任務,如果此時工作線程數量為0的話,那么會創建一個工作線程(非核心線程)出來;
(3):poolSize = corePoolSize,并且此時阻塞隊列已經滿了,那么會直接創建新的工作線程(非核心線程)來處理阻塞隊列中的任務;
(4):poolSize = maximumPoolSize,并且此時阻塞隊列也滿了的話,那么會觸發拒絕機制,具體決絕策略采用的是什么就要看我們創建ThreadPoolExecutor的時候傳入的RejectExecutionHandler參數了;
接下來就是線程池是怎么做到重用線程的呢?
個人認為線程池里面重用線程的工作是在getTask里面實現的,在getTask里面是存在兩個for死循環嵌套的,他會不斷的從阻塞對列里面取出需要執行的任務,返回給我們的runWorker方法里面,而在runWorker方法里面只要getTask返回的任務不是空就會執行該任務的run方法來處理它,這樣一直執行下去,直到getTask返回空為止,此時的情況就是阻塞隊列里面沒有任務了,這樣一個線程處理完一個任務之后接著再處理阻塞隊列中的另一個任務,當然在線程池中的不同線程是可以并發處理阻塞隊列中的任務的,最后在阻塞隊列內部不存在任務的時候會去判斷是否需要回收Worker對象,其實Worker對象的個數就是線程池中線程的個數,至于什么情況才需要回收,上面已經說了,就是四種情況了;
最后就是線程池是怎樣被關閉的呢?
涉及到線程池的關閉,需要用到兩個方法,shutdown和shutdownNow,他們都是位于ThreadPoolExecutor里面的,對于shutdown的話,他會將線程池狀態切換成Shutdown,此時是不會影響對阻塞隊列中任務執行的,但是會拒絕執行新加進來的任務,同時會回收閑置的Worker;而shutdownNow方法會將線程池狀態切換成Stop,此時既不會再去處理阻塞隊列里面的任務,也不會去處理新加進來的任務,同時會回收所有Worker;
線程池簡介:
多線程技術主要解決處理器單元內多個線程執行的問題,它可以顯著減少處理器單元的閑置時間,增加處理器單元的吞吐能力。
假設一個服務器完成一項任務所需時間為:T1 創建線程時間,T2 在線程中執行任務的時間,T3 銷毀線程時間。
如果:T1 + T3 遠大于 T2,則可以采用線程池,以提高服務器性能。
一個線程池包括以下四個基本組成部分:
1、線程池管理器(ThreadPool):用于創建并管理線程池,包括 創建線程池,銷毀線程池,添加新任務;
2、工作線程(PoolWorker):線程池中線程,在沒有任務時處于等待狀態,可以循環的執行任務;
3、任務接口(Task):每個任務必須實現的接口,以供工作線程調度任務的執行,它主要規定了任務的入口,任務執行完后的收尾工作,任務的執行狀態等;
4、任務隊列(taskQueue):用于存放沒有處理的任務。提供一種緩沖機制。
線程池技術正是關注如何縮短或調整T1,T3時間的技術,從而提高服務器程序性能的。它把T1,T3分別安排在服務器程序的啟動和結束的時間段或者一些空閑的時間段,這樣在服務器程序處理客戶請求時,不會有T1,T3的開銷了。
線程池不僅調整T1,T3產生的時間段,而且它還顯著減少了創建線程的數目,看一個例子:
假設一個服務器一天要處理50000個請求,并且每個請求需要一個單獨的線程完成。在線程池中,線程數一般是固定的,所以產生線程總數不會超過線程池中線程的數目,而如果服務器不利用線程池來處理這些請求則線程總數為50000。一般線程池大小是遠小于50000。所以利用線程池的服務器程序不會為了創建50000而在處理請求時浪費時間,從而提高效率。
代碼實現中并沒有實現任務接口,而是把Runnable對象加入到線程池管理器(ThreadPool),然后剩下的事情就由線程池管理器(ThreadPool)來完成了
package?mine.util.thread;??
import?java.util.LinkedList;??
import?java.util.List;??
/**?
*?線程池類,線程管理器:創建線程,執行任務,銷毀線程,獲取線程基本信息?
*/??
public?final?class?ThreadPool?{??
//?線程池中默認線程的個數為5??
private?static?int?worker_num?=?5;??
//?工作線程??
private?WorkThread[]?workThrads;??
//?未處理的任務??
private?static?volatile?int?finished_task?=?0;??
//?任務隊列,作為一個緩沖,List線程不安全??
private?ListRunnable?taskQueue?=?new?LinkedListRunnable();??
private?static?ThreadPool?threadPool;??
//?創建具有默認線程個數的線程池??
private?ThreadPool()?{??
this(5);??
}??
//?創建線程池,worker_num為線程池中工作線程的個數??
private?ThreadPool(int?worker_num)?{??
ThreadPool.worker_num?=?worker_num;??
workThrads?=?new?WorkThread[worker_num];??
for?(int?i?=?0;?i??worker_num;?i++)?{??
workThrads[i]?=?new?WorkThread();??
workThrads[i].start();//?開啟線程池中的線程??
}??
}??
//?單態模式,獲得一個默認線程個數的線程池??
public?static?ThreadPool?getThreadPool()?{??
return?getThreadPool(ThreadPool.worker_num);??
}??
//?單態模式,獲得一個指定線程個數的線程池,worker_num(0)為線程池中工作線程的個數??
//?worker_num=0創建默認的工作線程個數??
public?static?ThreadPool?getThreadPool(int?worker_num1)?{??
if?(worker_num1?=?0)??
worker_num1?=?ThreadPool.worker_num;??
if?(threadPool?==?null)??
threadPool?=?new?ThreadPool(worker_num1);??
return?threadPool;??
}??
//?執行任務,其實只是把任務加入任務隊列,什么時候執行有線程池管理器覺定??
public?void?execute(Runnable?task)?{??
synchronized?(taskQueue)?{??
taskQueue.add(task);??
taskQueue.notify();??
}??
}??
//?批量執行任務,其實只是把任務加入任務隊列,什么時候執行有線程池管理器覺定??
public?void?execute(Runnable[]?task)?{??
synchronized?(taskQueue)?{??
for?(Runnable?t?:?task)??
taskQueue.add(t);??
taskQueue.notify();??
}??
}??
//?批量執行任務,其實只是把任務加入任務隊列,什么時候執行有線程池管理器覺定??
public?void?execute(ListRunnable?task)?{??
synchronized?(taskQueue)?{??
for?(Runnable?t?:?task)??
taskQueue.add(t);??
taskQueue.notify();??
}??
}??
//?銷毀線程池,該方法保證在所有任務都完成的情況下才銷毀所有線程,否則等待任務完成才銷毀??
public?void?destroy()?{??
while?(!taskQueue.isEmpty())?{//?如果還有任務沒執行完成,就先睡會吧??
try?{??
Thread.sleep(10);??
}?catch?(InterruptedException?e)?{??
e.printStackTrace();??
}??
}??
//?工作線程停止工作,且置為null??
for?(int?i?=?0;?i??worker_num;?i++)?{??
workThrads[i].stopWorker();??
workThrads[i]?=?null;??
}??
threadPool=null;??
taskQueue.clear();//?清空任務隊列??
}??
//?返回工作線程的個數??
public?int?getWorkThreadNumber()?{??
return?worker_num;??
}??
//?返回已完成任務的個數,這里的已完成是只出了任務隊列的任務個數,可能該任務并沒有實際執行完成??
public?int?getFinishedTasknumber()?{??
return?finished_task;??
}??
//?返回任務隊列的長度,即還沒處理的任務個數??
public?int?getWaitTasknumber()?{??
return?taskQueue.size();??
}??
//?覆蓋toString方法,返回線程池信息:工作線程個數和已完成任務個數??
@Override??
public?String?toString()?{??
return?"WorkThread?number:"?+?worker_num?+?"??finished?task?number:"??
+?finished_task?+?"??wait?task?number:"?+?getWaitTasknumber();??
}??
/**?
*?內部類,工作線程?
*/??
private?class?WorkThread?extends?Thread?{??
//?該工作線程是否有效,用于結束該工作線程??
private?boolean?isRunning?=?true;??
/*?
*?關鍵所在啊,如果任務隊列不空,則取出任務執行,若任務隊列空,則等待?
*/??
@Override??
public?void?run()?{??
Runnable?r?=?null;??
while?(isRunning)?{//?注意,若線程無效則自然結束run方法,該線程就沒用了??
synchronized?(taskQueue)?{??
while?(isRunning??taskQueue.isEmpty())?{//?隊列為空??
try?{??
taskQueue.wait(20);??
}?catch?(InterruptedException?e)?{??
e.printStackTrace();??
}??
}??
if?(!taskQueue.isEmpty())??
r?=?taskQueue.remove(0);//?取出任務??
}??
if?(r?!=?null)?{??
r.run();//?執行任務??
}??
finished_task++;??
r?=?null;??
}??
}??
//?停止工作,讓該線程自然執行完run方法,自然結束??
public?void?stopWorker()?{??
isRunning?=?false;??
}??
}??
}
線程池通俗的描述就是預先創建若干空閑線程 等到需要用多線程去處理事務的時候去喚醒某些空閑線程執行處理任務 這樣就省去了頻繁創建線程的時間 因為頻 繁創建線程是要耗費大量的CPU資源的 如果一個應用程序需要頻繁地處理大量并發事務 不斷的創建銷毀線程往往會大大地降低系統的效率 這時候線程池就派 上用場了
本文旨在使用Java語言編寫一個通用的線程池 當需要使用線程池處理事務時 只需按照指定規范封裝好事務處理對象 然后用已有的線程池對象去自動選擇空 閑線程自動調用事務處理對象即可 并實現線程池的動態修改(修改當前線程數 最大線程數等) 下面是實現代碼
//ThreadTask java
package polarman threadpool;
/** *//**
*線程任務
* @author ryang
*
*/
public interface ThreadTask {
public void run();
}
//PooledThread java
package polarman threadpool;
import java util Collection; import java util Vector;
/** *//**
*接受線程池管理的線程
* @author ryang
*
*/
public class PooledThread extends Thread {
protected Vector tasks = new Vector();
protected boolean running = false;
protected boolean stopped = false;
protected boolean paused = false;
protected boolean killed = false;
private ThreadPool pool;
public PooledThread(ThreadPool pool) { this pool = pool;
}
public void putTask(ThreadTask task) { tasks add(task);
}
public void putTasks(ThreadTask[] tasks) { for(int i= ; itasks length; i++) this tasks add(tasks[i]);
}
public void putTasks(Collection tasks) { this tasks addAll(tasks);
}
protected ThreadTask popTask() { if(tasks size() ) return (ThreadTask)tasks remove( );
else
return null;
}
public boolean isRunning() {
return running;
}
public void stopTasks() {
stopped = true;
}
public void stopTasksSync() {
stopTasks();
while(isRunning()) { try {
sleep( );
} catch (InterruptedException e) {
}
}
}
public void pauseTasks() {
paused = true;
}
public void pauseTasksSync() {
pauseTasks();
while(isRunning()) { try {
sleep( );
} catch (InterruptedException e) {
}
}
}
public void kill() { if(!running)
interrupt();
else
killed = true;
}
public void killSync() {
kill();
while(isAlive()) { try {
sleep( );
} catch (InterruptedException e) {
}
}
}
public synchronized void startTasks() {
running = true;
this notify();
}
public synchronized void run() { try { while(true) { if(!running || tasks size() == ) { pool notifyForIdleThread(); //System out println(Thread currentThread() getId() + : 空閑 ); this wait(); }else {
ThreadTask task;
while((task = popTask()) != null) { task run(); if(stopped) {
stopped = false;
if(tasks size() ) { tasks clear(); System out println(Thread currentThread() getId() + : Tasks are stopped );
break;
}
}
if(paused) {
paused = false;
if(tasks size() ) { System out println(Thread currentThread() getId() + : Tasks are paused );
break;
}
}
}
running = false;
}
if(killed) {
killed = false;
break;
}
}
}catch(InterruptedException e) {
return;
}
//System out println(Thread currentThread() getId() + : Killed );
}
}
//ThreadPool java
package polarman threadpool;
import java util Collection; import java util Iterator; import java util Vector;
/** *//**
*線程池
* @author ryang
*
*/
public class ThreadPool {
protected int maxPoolSize;
protected int initPoolSize;
protected Vector threads = new Vector();
protected boolean initialized = false;
protected boolean hasIdleThread = false;
public ThreadPool(int maxPoolSize int initPoolSize) { this maxPoolSize = maxPoolSize; this initPoolSize = initPoolSize;
}
public void init() {
initialized = true;
for(int i= ; iinitPoolSize; i++) {
PooledThread thread = new PooledThread(this);
thread start(); threads add(thread);
}
//System out println( 線程池初始化結束 線程數= + threads size() + 最大線程數= + maxPoolSize);
}
public void setMaxPoolSize(int maxPoolSize) { //System out println( 重設最大線程數 最大線程數= + maxPoolSize); this maxPoolSize = maxPoolSize;
if(maxPoolSize getPoolSize())
setPoolSize(maxPoolSize);
}
/** *//**
*重設當前線程數
* 若需殺掉某線程 線程不會立刻殺掉 而會等到線程中的事務處理完成* 但此方法會立刻從線程池中移除該線程 不會等待事務處理結束
* @param size
*/
public void setPoolSize(int size) { if(!initialized) {
initPoolSize = size;
return;
}else if(size getPoolSize()) { for(int i=getPoolSize(); isize imaxPoolSize; i++) {
PooledThread thread = new PooledThread(this);
thread start(); threads add(thread);
}
}else if(size getPoolSize()) { while(getPoolSize() size) { PooledThread th = (PooledThread)threads remove( ); th kill();
}
}
//System out println( 重設線程數 線程數= + threads size());
}
public int getPoolSize() { return threads size();
}
protected void notifyForIdleThread() {
hasIdleThread = true;
}
protected boolean waitForIdleThread() {
hasIdleThread = false;
while(!hasIdleThread getPoolSize() = maxPoolSize) { try { Thread sleep( ); } catch (InterruptedException e) {
return false;
}
}
return true;
}
public synchronized PooledThread getIdleThread() { while(true) { for(Iterator itr=erator(); itr hasNext();) { PooledThread th = (PooledThread)itr next(); if(!th isRunning())
return th;
}
if(getPoolSize() maxPoolSize) {
PooledThread thread = new PooledThread(this);
thread start(); threads add(thread);
return thread;
}
//System out println( 線程池已滿 等待 );
if(waitForIdleThread() == false)
return null;
}
}
public void processTask(ThreadTask task) {
PooledThread th = getIdleThread();
if(th != null) { th putTask(task); th startTasks();
}
}
public void processTasksInSingleThread(ThreadTask[] tasks) {
PooledThread th = getIdleThread();
if(th != null) { th putTasks(tasks); th startTasks();
}
}
public void processTasksInSingleThread(Collection tasks) {
PooledThread th = getIdleThread();
if(th != null) { th putTasks(tasks); th startTasks();
}
}
}
下面是線程池的測試程序
//ThreadPoolTest java
import java io BufferedReader; import java io IOException; import java io InputStreamReader;
import polarman threadpool ThreadPool; import polarman threadpool ThreadTask;
public class ThreadPoolTest {
public static void main(String[] args) { System out println( quit 退出 ); System out println( task A 啟動任務A 時長為 秒 ); System out println( size 設置當前線程池大小為 ); System out println( max 設置線程池最大線程數為 ); System out println();
final ThreadPool pool = new ThreadPool( ); pool init();
Thread cmdThread = new Thread() { public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System in));
while(true) { try { String line = reader readLine(); String words[] = line split( ); if(words[ ] equalsIgnoreCase( quit )) { System exit( ); }else if(words[ ] equalsIgnoreCase( size ) words length = ) { try { int size = Integer parseInt(words[ ]); pool setPoolSize(size); }catch(Exception e) {
}
}else if(words[ ] equalsIgnoreCase( max ) words length = ) { try { int max = Integer parseInt(words[ ]); pool setMaxPoolSize(max); }catch(Exception e) {
}
}else if(words[ ] equalsIgnoreCase( task ) words length = ) { try { int timelen = Integer parseInt(words[ ]); SimpleTask task = new SimpleTask(words[ ] timelen * ); pool processTask(task); }catch(Exception e) {
}
}
} catch (IOException e) { e printStackTrace();
}
}
}
};
cmdThread start();
/**//*
for(int i= ; i ; i++){
SimpleTask task = new SimpleTask( Task + i (i+ )* ); pool processTask(task);
}*/
}
}
class SimpleTask implements ThreadTask {
private String taskName;
private int timeLen;
public SimpleTask(String taskName int timeLen) { this taskName = taskName; this timeLen = timeLen;
}
public void run() { System out println(Thread currentThread() getId() +
: START TASK + taskName + );
try { Thread sleep(timeLen); } catch (InterruptedException e) {
}
System out println(Thread currentThread() getId() +
: END TASK + taskName + );
}
}
使用此線程池相當簡單 下面兩行代碼初始化線程池
ThreadPool pool = new ThreadPool( ); pool init();
要處理的任務實現ThreadTask 接口即可(如測試代碼里的SimpleTask) 這個接口只有一個方法run()
兩行代碼即可調用
lishixinzhi/Article/program/Java/hx/201311/27203
網頁題目:java線程池的實現代碼 java線程池實現
URL鏈接:http://m.newbst.com/article0/hjjpio.html
成都網站建設公司_創新互聯,為您提供ChatGPT、、微信小程序、軟件開發、網站制作、全網營銷推廣
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯