【future的概念:inte***ce future,表示非同步計算的結果,future有個get方法而獲取結果只有在計算完成時獲取,否則會一直阻塞直到任務轉入完成狀態,然後會返回結果或者丟擲異常。
相對於繼承thread來建立執行緒方式,使用runnable可以讓你的實現類同時實現多個介面,而相對於callable及future,runnable方法並不返回任務執行結果且不能丟擲異常。
【inte***ce future具有如下方法:
public inte***ce future
補充:futuretask:包裝器,可以將callable轉換成為future與runnable,它同時實現了二者的介面。
callable:可以為非同步方法返回計算結果。
【下面我們實現一種基於future的場景
public class exercise
}public string query() throws interruptedexception
}【反思一些問題:
1.每個非同步方法都需要新開啟乙個執行緒這樣很消耗資源。
2.每次都要new乙個thread挺麻煩的。
【解決方案:
使用執行緒池:
1.構建乙個新的執行緒是有代價的,因為設計到與作業系統的互動。如果程式中建立了大量的並且生命週期很短的執行緒,我們應該使用執行緒池。
乙個執行緒池包含很多準備執行的空閒執行緒,每當run()執行完畢後,執行緒不會死亡而是回到執行緒池準備為下乙個請求提供服務。
2.另乙個使用執行緒池的理由是減少併發執行緒數。建立大量執行緒會大大降低效能甚至拖垮虛擬機器。
【executor:
executors類有許多靜態方法可建立執行緒池。例如:
executors.newcachedthreadpool():對於乙個任務,有空閒執行緒可用則會立即執行,否則建立乙個新的執行緒。空閒執行緒存活60s。
executors.newfixedthreadpool(n):構建具有固定大小的執行緒池,若任務多餘空閒執行緒數,則將多餘任務放置等待佇列中。
executors.newsinglethreadexecutor():只有乙個空閒執行緒的執行緒池,任務執行乙個接乙個;
以上三個方法返回executorservice介面的threadpoolexecutor物件。
核心(簡介):
threadpoolexecutor
public class threadpoolexecutor extends abstractexecutorservice
引數含義:
corepoolsize:核心池的大小,這個引數跟後面講述的執行緒池的實現原理有非常大的關係。
在建立了執行緒池後,預設情況下,執行緒池中並沒有任何執行緒,而是等待有任務到來才建立執行緒去執行任務,除非呼叫了prestartallcorethreads()或者prestartcorethread()方法。
從這2個方法的名字就可以看出,是預建立執行緒的意思,即在沒有任務到來之前就建立corepoolsize個執行緒或者乙個執行緒。預設情況下,在建立了執行緒池後,執行緒池中的執行緒數為0。
當有任務來之後,就會建立乙個執行緒去執行任務,當執行緒池中的執行緒數目達到corepoolsize後,就會把到達的任務放到快取佇列當中;
keepalivetime:表示執行緒沒有任務執行時最多保持多久時間會終止。預設情況下,只有當執行緒池中的執行緒數大於corepoolsize時,keepalivetime才會起作用。
直到執行緒池中的執行緒數不大於corepoolsize,即當執行緒池中的執行緒數大於corepoolsize時,如果乙個執行緒空閒的時間達到keepalivetime,則會終止,直到執行緒池中的執行緒數不超過corepoolsize。
unit:引數keepalivetime的時間單位
workqueue:乙個阻塞佇列,用來儲存等待執行的任務,這個引數的選擇也很重要,會對執行緒池的執行過程產生重大影響,一般來說,這裡的阻塞佇列有以下幾種選擇:
arrayblockingqueue;linkedblockingqueue;synchronousqueue;
threadfactory:執行緒工廠,主要用來建立執行緒;
handler:表示當拒絕處理任務時的策略,有以下四種取值:
threadpoolexecutor.abortpolicy:丟棄任務並丟擲rejectedexecutionexception異常。
threadpoolexecutor.discardpolicy:也是丟棄任務,但是不丟擲異常。
threadpoolexecutor.discardoldestpolicy:丟棄佇列最前面的任務,然後重新嘗試執行任務(重複此過程)
threadpoolexecutor.callerrunspolicy:由呼叫執行緒處理該任務
使用連線池應該做的事:
1.呼叫executors的靜態方法建立執行緒池。
2.呼叫submit(),提交乙個callable物件或者runnable物件。
3.儲存好獲得的future<>物件,其中是計算結果(如果提交的是callable)。
4.沒有任何任務再提交的時候使用shutdown().
public class taskexercise
}class calltask implements callable
}class runtask implements runnable
}【控制任務組:
有時使用執行器更有意義的場景是控制一組相關任務。
1.shutdownnow():取消所有任務
2.invokeany():提交所有物件到乙個callable物件集合,並返回某個已完成的任務結果。例如:如果你願意接受任何一種解決方案的話。
還有其他一些方法等我們真正用到時再學習好了~
【補充:
spring中實現非同步呼叫:spring為任務排程與非同步方法執行提供了註解支援。通過在方法上設定@async註解,可使得方法被非同步呼叫。
也就是說呼叫者會在呼叫時立即返回,而被呼叫方法的實際執行是交給spring的taskexecutor來完成。如果是有返回值的話記得:
介面返回future<>,實現返回asyncresult<>。
java併發程式設計學習2 Future
inte ce future,表示非同步計算的結果,future有個get方法而獲取結果只有在計算完成時獲取,否則會一直阻塞直到任務轉入完成狀態,然後會返回結果或者丟擲異常。相對於繼承thread來建立執行緒方式,使用runnable可以讓你的實現類同時實現多個介面,而相對於callable及fut...
JAVA併發程式設計學習
併發程式設計主要目的是為了在相同的時間內讓程式執行得更快或者處理更多的任務。為了實現這一目的,併發程式設計會面臨很多的挑戰。併發程式設計必然會帶來多執行緒之間的問題,比如上下文之間的切換,執行緒死鎖,以及硬體資源的限制。無論是單核還是多核處理器都支援多執行緒。在單核處理器中,cpu會給每個執行緒分配...
Java併發程式設計實踐(2)
1 同步容器類 hashmap和hashtable的區別 hashmap底層繼承abstractmap抽象類,並實現map介面,hashtable底層繼承dictionary類並實現map介面 hashmap初始話大小為16而hashtable初始化大小為11,hashmap是非執行緒安全的而has...