1. java線程池怎麼實現
要想理解清楚java線程池實現原理,明白下面幾個問題就可以了:
(1):線程池存在哪些狀態,這些狀態之間是如何進行切換的呢?
(2):線程池的種類有哪些?
(3):創建線程池需要哪些參數,這些參數的具體含義是什麼?
(4):將任務添加到線程池之後運行流程?
(5):線程池是怎麼做到重用線程的呢?
(6):線程池的關閉
首先回答第一個問題:線程池存在哪些狀態;
查看ThreadPoolExecutor源碼便知曉:
[java]view plain
//runStateisstoredinthehigh-orderbits
privatestaticfinalintRUNNING=-1<<COUNT_BITS;
privatestaticfinalintSHUTDOWN=0<<COUNT_BITS;
privatestaticfinalintSTOP=1<<COUNT_BITS;
privatestaticfinalintTIDYING=2<<COUNT_BITS;
=3<<COUNT_BITS;
存在5種狀態:
<1>Running:可以接受新任務,同時也可以處理阻塞隊列裡面的任務;
<2>Shutdown:不可以接受新任務,但是可以處理阻塞隊列裡面的任務;
<3>Stop:不可以接受新任務,也不處理阻塞隊列裡面的任務,同時還中斷正在處理的任務;
<4>Tidying:屬於過渡階段,在這個階段表示所有的任務已經執行結束了,當前線程池中是不存在有效的線程的,並且將要調用terminated方法;
<5>Terminated:終止狀態,這個狀態是在調用完terminated方法之後所處的狀態;
那麼這5種狀態之間是如何進行轉換的呢?查看ThreadPoolExecutor源碼裡面的注釋便可以知道啦:
[java]view plain
*RUNNING->SHUTDOWN
*Oninvocationofshutdown(),perhapsimplicitlyinfinalize()
*(RUNNINGorSHUTDOWN)->STOP
*OninvocationofshutdownNow()
*SHUTDOWN->TIDYING
*Whenbothqueueandpoolareempty
*STOP->TIDYING
*Whenpoolisempty
*TIDYING->TERMINATED
*Whentheterminated()hookmethodhascompleted
從上面可以看到,在調用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):ScheledThreadPool:任務線程池,這種線程池中核心線程的數量是固定的,而對於非核心線程的數量是不限制的,同時對於非核心線程是存在超時淘汰機制的,主要適用於執行定時任務或者周期性任務的場景;
(4):SingleThreadPool:單一線程池,線程池裡面只有一個線程,同時也不存在非核心線程,感覺像是FixedThreadPool的特殊版本,他主要用於確保任務在同一線程中的順序執行,有點類似於進行同步吧;
接下來我們來看第三個問題,創建線程池需要哪些參數:
同樣查看ThreadPoolExecutor源碼,查看創建線程池的構造函數:
[java]view plain
publicThreadPoolExecutor(intcorePoolSize,
intmaximumPoolSize,
longkeepAliveTime,
TimeUnitunit,
BlockingQueue<Runnable>workQueue,
ThreadFactorythreadFactory,
)
不管你調用的是ThreadPoolExecutor的哪個構造函數,最終都會執行到這個構造函數的,這個構造函數有7個參數,正是由於對這7個參數值的賦值不同,造成生成不同類型的線程池,比如我們常見的CachedThreadPoolExecutor、FixedThreadPoolExecutor
SingleThreadPoolExecutor、ScheledThreadPoolExecutor,我們老看看這幾個參數的具體含義:
<1>corePoolSize:線程池中核心線程的數量;當提交一個任務到線程池的時候,線程池會創建一個線程來執行執行任務,即使有其他空閑的線程存在,直到線程數達到corePoolSize時不再創建,這時候會把提交的新任務放入到阻塞隊列中,如果調用了線程池的preStartAllCoreThreads方法,則會在創建線程池的時候初始化出來核心線程;
<2>maximumPoolSize:線程池允許創建的最大線程數;如果阻塞隊列已經滿了,同時已經創建的線程數小於最大線程數的話,那麼會創建新的線程來處理阻塞隊列中的任務;
<3>keepAliveTime:線程活動保持時間,指的是工作線程空閑之後繼續存活的時間,默認情況下,這個參數只有線程數大於corePoolSize的時候才會起作用,即當線程池中的線程數目大於corePoolSize的時候,如果某一個線程的空閑時間達到keepAliveTime,那麼這個線程是會被終止的,直到線程池中的線程數目不大於corePoolSize;如果調用allowCoreThreadTimeOut的話,在線程池中線程數量不大於corePoolSize的時候,keepAliveTime參數也可以起作用的,知道線程數目為0為止;
<4>unit:參數keepAliveTime的時間單位;
<5>workQueue:阻塞隊列;用於存儲等待執行的任務,有四種阻塞隊列類型,ArrayBlockingQueue(基於數組的有界阻塞隊列)、LinkedBlockingQueue(基於鏈表結構的阻塞隊列)、SynchronousQueue(不存儲元素的阻塞隊列)、PriorityBlockingQueue(具有優先順序的阻塞隊列);
<6>threadFactory:用於創建線程的線程工廠;
<7>handler:當阻塞隊列滿了,且沒有空閑線程的情況下,也就是說這個時候,線程池中的線程數目已經達到了最大線程數量,處於飽和狀態,那麼必須採取一種策略來處理新提交的任務,我們可以自己定義處理策略,也可以使用系統已經提供給我們的策略,先來看看系統為我們提供的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
if(wc>=CAPACITY||
wc>=(core?corePoolSize:maximumPoolSize))
returnfalse;
如果當前線程數量超過maximumPoolSize的話,直接就會調用return方法,返回false;
其實到這里我們很明顯可以知道,一個線程池中線程的數量實際上就是這個線程池中Worker的數量,如果Worker的大小超過了corePoolSize,那麼任務都在阻塞隊列裡面了,Worker是Java對我們任務的一個封裝類,他的聲明是醬紫的:
[java]view plain
privatefinalclassWorker
implementsRunnable
可以看到他實現了Runnable介面,他是在addWorker方法裡面通過new Worker(firstTask)創建的,我們來看看他的構造函數就知道了:
[java]view plain
Worker(RunnablefirstTask){
setState(-1);//
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
public<T>Future<T>submit(Callable<T>task){
if(task==null)thrownewNullPointerException();
RunnableFuture<T>ftask=newTaskFor(task);
execute(ftask);
returnftask;
}
看到沒有呢,實際上在你傳入實現了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;
2. java如何寫一個線程池(線程池大小可定義為3),
packagecn.sdeit.servlet;
importjava.io.IOException;
importjava.io.PrintWriter;
importjava.sql.Connection;
importjava.sql.PreparedStatement;
importjava.sql.SQLException;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importcn.sdeit.beans.Team;
importcn.sdeit.beans.User;
importcn.sdeit.mysql.ConnectMySql;
/**
*
*/
@WebServlet(name="JoinTeam",urlPatterns={"/JoinTeam"})
{
=1L;
privateStringcaptainName=null;
privateStringteamName=null;
privatePrintWriterwriter=null;
/**
*@seeHttpServlet#HttpServlet()
*/
publicJoinTeam()
{
();
}
protectedvoiddoGet(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
writer=response.getWriter();
captainName=request.getParameter("name");
teamName=request.getParameter("team");
if(teamName.equals((newTeam()).getTeamNameByCaptainName(captainName)))
{
intresult=joinTeam(((User)request.getSession().getAttribute("oldUser")).getEmail());
if(result==0)
{
showErrorMessage("抱歉!</br>伺服器內部錯誤,加入隊伍失敗!請及時反饋管理員!");
}
else
{
response.sendRedirect("mine.jsp");
}
}
else
{
showErrorMessage("抱歉!</br>沒有找到符合條件的團隊!請聯系您的隊長解決,若信息無誤,且問題一直出現,請聯系管理員!");
writer.flush();
writer.close();
}
}
privatevoidshowErrorMessage(Stringerror)
{
writer.write(error);
writer.flush();
writer.close();
}
privateintjoinTeam(Stringemail)
{
intposition=(newTeam()).getMinEmptyMemberPosition(teamName);
intresult=0;
if(position==-1)
{
showErrorMessage("抱歉!</br>此小組人數已達到上限,請更換隊伍或者協商隊長調整組員結構!");
}
else
{
Connectionconnection=ConnectMySql.createConnection();
Stringsql="updateteamsetmember"+position+""+"=?wherename=?";
PreparedStatementprepared=ConnectMySql.createPreparedStatement(connection,sql);
try
{
prepared.setString(1,email);
prepared.setString(2,teamName);
result=prepared.executeUpdate();
connection.close();
prepared.close();
}catch(SQLExceptione)
{
e.printStackTrace();
}
}
returnresult;
}
}
3. 幾種開源Java Web容器線程池的實現方法簡介
其中Resin從V3.0後需要購買才能用於商業目的,而其他兩種則是純開源的。可以分別從他們的網站上下載最新的二進制包和源代碼。
作為Web容器,需要承受較高的訪問量,能夠同時響應不同用戶的請求,能夠在惡劣環境下保持較高的穩定性和健壯性。在HTTP伺服器領域,ApacheHTTPD的效率是最高的,也是最為穩定的,但它只能處理靜態頁面的請求,如果需要支持動態頁面請求,則必須安裝相應的插件,比如mod_perl可以處理Perl腳本,mod_python可以處理Python腳本。
上面介紹的三中Web容器,都是使用Java編寫的HTTP伺服器,當然他們都可以嵌到Apache中使用,也可以獨立使用。分析它們處理客戶請求的方法有助於了解Java多線程和線程池的實現方法,為設計強大的多線程伺服器打好基礎。
Tomcat是使用最廣的Java Web容器,功能強大,可擴展性強。最新版本的Tomcat(5.5.17)為了提高響應速度和效率,使用了Apache Portable Runtime(APR)作為最底層,使用了APR中包含Socket、緩沖池等多種技術,性能也提高了。APR也是Apache HTTPD的最底層。可想而知,同屬於ASF(Apache Software Foundation)中的成員,互補互用的情況還是很多的,雖然使用了不同的開發語言。
Tomcat 的線程池位於tomcat-util.jar文件中,包含了兩種線程池方案。方案一:使用APR的Pool技術,使用了JNI;方案二:使用Java實現的ThreadPool。這里介紹的是第二種。如果想了解APR的Pool技術,可以查看APR的源代碼。
ThreadPool默認創建了5個線程,保存在一個200維的線程數組中,創建時就啟動了這些線程,當然在沒有請求時,它們都處理等待狀態(其實就是一個while循環,不停的等待notify)。如果液桐有請求時,空閑線程會被喚醒執行用戶的請求。
具體的請求過程是:服務啟動時,創建一個一維線程數組(maxThread=200個),並創建空閑線程(minSpareThreads=5個)隨時等待用戶請求。當有用戶請求時,調用 threadpool.runIt(ThreadPoolRunnable)方法,將一個需要執行的實例傳給ThreadPool中。其中用戶需要執行的實例必須實現ThreadPoolRunnable介面。 ThreadPool首先查找空閑的線程,如果有則用它運行要執行ThreadPoolRunnable;如果沒有空閑線程並且沒有超過 maxThreads,就一次性創建minSpareThreads個空閑線程;如果已經超過了maxThreads了,就等待空閑線程了。總之,要找到空閑的線程,以便用它執行實例。找到後,將該線程從線程數組中移走。接著喚醒已經找到的空閑線程,用它運行執行實例(ThreadPoolRunnable)。運行完ThreadPoolRunnable後,就將該線程鬧棗坦重新放到線程數組中,作為空閑線程供後續使用。
由此可以看出,Tomcat的線程池實現是比較簡單的,ThreadPool.java也只有840行代碼。用一個一維數組保存空閑的線程,每次以一個較小步伐(5個)創建空閑線程並放到線程池中。使岩辯用時從數組中移走空閑的線程,用完後,再歸還給線程池。
4. JAVA 線程池使用
package tender nmem eris drawexpert service impl;
import java util List;
import ncurrent ExecutorService;
import ncurrent Executors;
import llections map ListOrderedMap;
/**
吵擾* 類 線程池類 控制程序線程實改銷例個數 並實例線程
* @author yangtb
* 時間 / /
*
*/
public class ThreadPool {
private ExecutorService exe=null;//線程池
public ThreadPool(int pool_size)
{
exe=Executors newFixedThreadPool(pool_size);//創建線程池
System out println( the server is ready );
}
/**
* 運行循環實例線程 根據要實例的線程個數 傳入條件ID
* @param worknum
*/
public void server(int worknum String id)
{
int i= ;
while(i<worknum)
{
//實例指定升殲旦個線程
WorkerThreadImpl t = new WorkerThreadImpl(id);
exe execute(t);//放入線程池
i++;
}
}
lishixin/Article/program/Java/hx/201311/26215
5. java創建線程池有哪些
ava通過Executors提供四種線程池,分別為:
newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
newFixedThreadPool
創建一個定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。
newScheledThreadPool
創建一個定長線程池,支持定時及周期性任務執行。
newSingleThreadExecutor
創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO,
LIFO,
優先順序)執行。
6. 創建線程有幾種方式和Java中常用的線程池
java創建線程的方式有三種
第一種是繼承Thread類 實現方法run() 不可以拋異常 無返回值
第二種回是答實現Runnable介面 實現方法run() 不可以拋異常 無返回值
第三種是實現Callable<T>介面,介面中要覆蓋的方法是 public <T> call() 注意:此方法可以拋異常,而前兩種不能 而且此方法可以有返回值
第三種如何運行呢 Callable介面在util.concurrent包中,由線程池提交
import java.util.concurrent.*;
ExecutorService e = Executors.newFixedThreadPool(10); 參數表示最多可以運行幾個線程
e.submit(); 這個裡面參數傳 實現Callable介面那個類的對象
7. 如何用java線程池做
當一個線程完成任務時,它會從隊列中取下一個任務來執行。
當一個線程無褲廳謹事可做,超過一定的時間(keepAliveTime)時,線程池會判斷,如果當前運行的線程數大於 corePoolSize,那麼這個線程就被停掉。所以線程池的所有任務完成後,它最終會收縮到 corePoolSize 的大小。
這樣的過程說明,並不是先加入任務就一定會先執行。假設隊列大小為 10,corePoolSize 為 3,maximumPoolSize 為 6,那麼當加入 20 個任務時,執行的順序就是這樣的:首先執行任務 1、2、3,然後任務 4~13 被放入隊列。這時候隊列滿了,任務 14、15、16 會被馬上執行,而任務 17~20 則胡基會拋伏岩出異常。最終順序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。
8. Java線程池
java常用的線程池有三種:
1.
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads)創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。在任意點,在大多數 nThreads 線程會處於處理任務的活動狀態。如果在所有線程處於活動狀態時提交附加任務,則在有可用線程之前,附加任務將在隊列中等待。如果在關閉前的執行期間由於失敗而導致任何線程終止,那麼一個新線程將代替它執行後續的任務(如果需要)。在某個線程被顯式地關閉之前,池中的線程將一直存在。
參數:
nThreads - 池中的線程數
返回:
新創建的線程池
拋出:
IllegalArgumentException - 如果 nThreads <= 0
2.
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor()創建一個使用單個 worker 線程的 Executor,以無界隊列方式來運行該線程。(注意,如果因為在關閉前的執行期間出現失敗而終止了此單個線程,那麼如果需要,一個新線程將代替它執行後續的任務)。可保證順序地執行各個任務,並且在任意給定的時間不會有多個線程是活動的。與其他等效的 newFixedThreadPool(1) 不同,可保證無需重新配置此方法所返回的執行程序即可使用其他的線程。
返回:
新創建的單線程 Executor
3.
newCachedThreadPool
public static ExecutorService newCachedThreadPool()創建一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們。對於執行很多短期非同步任務的程序而言,這些線程池通常可提高程序性能。調用 execute 將重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線程並添加到池中。終止並從緩存中移除那些已有 60 秒鍾未被使用的線程。因此,長時間保持空閑的線程池不會使用任何資源。注意,可以使用 ThreadPoolExecutor 構造方法創建具有類似屬性但細節不同(例如超時參數)的線程池。
返回:
新創建的線程池
9. java 怎麼實現線程池
最簡單的可以利用java.util.concurrent.Executors
調用Executors.newCachedThreadPool()獲取緩沖式線程池
Executors.newFixedThreadPool(int nThreads)獲取固定大小的線程池
10. Java線程池
線程池是一種多線程處理形式,處理過程中將任務添加隊列,然後在創建線程後自動啟動這些任務,每個線程都使用默認的堆棧大小,以默認的優先順序運行,並處在多線程單元中,如果某個線程在託管代碼中空閑,則線程池將插入另一個輔助線程來使所有處理器保持繁忙。如果所有線程池都始終保持繁忙,但隊列中包含掛起的工作,則線程池將在一段時間後輔助線程的數目永遠不會超過最大值。超過最大值的線程可以排隊,但他們要等到其他線程完成後才能啟動。
java裡面的線程池的頂級介面是Executor,Executor並不是一個線程池,而只是一個執行線程的工具,而真正的線程池是ExecutorService。
java中的有哪些線程池?
1.newCachedThreadPool創建一個可緩存線程池程
2.newFixedThreadPool 創建一個定長線程池
3.newScheledThreadPool 創建一個定長線程池
4.newSingleThreadExecutor 創建一個單線程化的線程池
————————————————