使用Executors工廠類建立執行緒池
介面Executor僅僅是一種規範,是一種宣告,是一種定義,並沒有實現任何的功能,所以大多數的情況下,需要使用介面的實現類來完成指定的功能,比如ThreadPoolExecutor類就是Executor的實現類,但ThreadPoolExecutor在使用上並不是那麼方便,在例項化時需要傳入很多歌引數,還要考慮執行緒的併發數等與執行緒池執行效率有關的引數,所以官方建議使用Executors工程類來建立執行緒池物件。
Executors工廠類的結構如下圖所示:
類Executors中的方法如下圖所示:
TP_1:使用newCachedThreadPool()方法建立無界執行緒池
使用Executors類的newCachedThreadPool()方法建立的是無界執行緒池,可以進行執行緒自動回收。所謂的“無界執行緒池”就是池中存放執行緒個數是理論上的Integer.MAX_VALUE最大值。
建立實驗用的專案Executors_1,類ThreadPool2NewCachedThreadPoolTest.java如下:
package com.yc.semephore_7; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPool2NewCachedThreadPoolTest { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(new Runnable(){ @Override public void run() { try { System.out.println("ThreadA begin:" + System.currentTimeMillis()); Thread.sleep(1000); System.out.println( "A"); System.out.println("ThreadA end:" + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } }); executorService.execute(new Runnable(){ @Override public void run() { try { System.out.println( "ThreadB begin:" + System.currentTimeMillis()); Thread.sleep(1000); System.out.println("B"); System.out.println( "ThreadB end:" + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }
執行的某一次結果如下:
從列印的時間來看,A和B幾乎是在相同的時間開始begin的,也就是建立了2個執行緒,2個執行緒之間是非同步執行的。繼續實驗,建立新類ThreadPool2NewCachedThreadPoolForTest.java如下:
package com.yc.semephore_7; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPool2NewCachedThreadPoolForTest { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for(int i = 0; i < 4; i ++){ executorService.execute(new Runnable(){ @Override public void run() { System.out.println( "run ->"); } }); } } }
執行結果如下:
TP_2:驗證newCachedThreadPool()建立為Thread池
前面的實驗都沒有驗證newCachedThreadPool()方法建立的是執行緒池。在本測試中將得到驗證。 建立專案Executors_2,類MyThread.java程式碼如下:package com.yc.executors;
public class MyThread implements Runnable{
private String userName;
public MyThread(String userName){
this.userName = userName;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "userName=" + userName + " begin-> " + System.currentTimeMillis());
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "userName=" + userName + " end-> " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
類ThreadPool2NewCachedThreadPoolIsTest.java程式碼如下:
package com.yc.executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPool2NewCachedThreadPoolIsTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0; i < 8; i ++){
executorService.execute(new MyThread( ""+(i+1) ) );
}
}
}
測試結果如下:
pool-1-thread-1userName=1 begin-> 1490516211122
pool-1-thread-3userName=3 begin-> 1490516211122
pool-1-thread-4userName=4 begin-> 1490516211122
pool-1-thread-7userName=7 begin-> 1490516211122
pool-1-thread-8userName=8 begin-> 1490516211123
pool-1-thread-2userName=2 begin-> 1490516211123
pool-1-thread-5userName=5 begin-> 1490516211123
pool-1-thread-6userName=6 begin-> 1490516211123
pool-1-thread-1userName=1 end-> 1490516212122
pool-1-thread-7userName=7 end-> 1490516212122
pool-1-thread-4userName=4 end-> 1490516212122
pool-1-thread-3userName=3 end-> 1490516212122
pool-1-thread-8userName=8 end-> 1490516212123
pool-1-thread-2userName=2 end-> 1490516212123
pool-1-thread-5userName=5 end-> 1490516212123
pool-1-thread-6userName=6 end-> 1490516212123
說明執行緒池物件建立是完全成功的,但還沒有達到池中執行緒物件可以服用的效果喲,下面要實現這樣的效果。 將ThreadPool2NewCachedThreadPoolIsTest.java程式碼改成如下所示:
package com.yc.executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPool2NewCachedThreadPoolIsTest {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0; i < 4; i ++){
executorService.execute(new MyThread( ""+(i+1) ) );
}
Thread.sleep(2 * 1000);
System.out.println("\n\n");
for(int i = 0; i < 4; i ++){
executorService.execute(new MyThread( ""+(i+1) ) );
}
}
}
測試結果如下所示:
pool-1-thread-1userName=1 begin-> 1490516619860
pool-1-thread-4userName=4 begin-> 1490516619861
pool-1-thread-2userName=2 begin-> 1490516619861
pool-1-thread-3userName=3 begin-> 1490516619860
pool-1-thread-3userName=3 end-> 1490516620861
pool-1-thread-2userName=2 end-> 1490516620861
pool-1-thread-4userName=4 end-> 1490516620861
pool-1-thread-1userName=1 end-> 1490516620861
pool-1-thread-3userName=1 begin-> 1490516621861
pool-1-thread-4userName=2 begin-> 1490516621861
pool-1-thread-2userName=4 begin-> 1490516621861
pool-1-thread-1userName=3 begin-> 1490516621861
pool-1-thread-3userName=1 end-> 1490516622861
pool-1-thread-1userName=3 end-> 1490516622861
pool-1-thread-4userName=2 end-> 1490516622861
pool-1-thread-2userName=4 end-> 1490516622861
TP_3:使用newCachedThreadPool(ThreadFactory)定製執行緒工廠
無界執行緒池中的Thread類還可以有程式設計師自己定製,方法newCachedThreadPool(ThreadFactory)就是解決這個問題。
建立專案Executors_3,建立MyThreadFactory,java執行緒工廠類程式碼如下:package com.yc.executors;
import java.util.concurrent.ThreadFactory;
public class MyThreadFactory implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
Thread rThread = new Thread(r);
rThread.setName("定製池中的執行緒->" + Math.random());
return rThread;
}
}
類MyThreadFactoryTest.java程式碼如下:
package com.yc.executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyThreadFactoryTest {
public static void main(String[] args) {
MyThreadFactory myThreadFactory = new MyThreadFactory();
ExecutorService executorService = Executors.newCachedThreadPool(myThreadFactory);
for(int i = 0; i < 8; i ++){
executorService.execute(new Runnable(){
@Override
public void run() {
System.out.println("我在使用 - " + Thread.currentThread().getName());
}
});
}
}
}
測試某一次的結果為:我在使用 - 定製池中的執行緒->0.7251183137194371
我在使用 - 定製池中的執行緒->0.7895540239349206
我在使用 - 定製池中的執行緒->0.055382936386370485
我在使用 - 定製池中的執行緒->0.7251183137194371
我在使用 - 定製池中的執行緒->0.4625204924896881
我在使用 - 定製池中的執行緒->0.5101540668259192
我在使用 - 定製池中的執行緒->0.7895540239349206
我在使用 - 定製池中的執行緒->0.8130499478281913
通過使用自定義的ThreadFactory介面實現類,實現了執行緒物件的定製型。
TP_4:使用newFixedThreadPool(int)方法建立有界執行緒池
方法newFixedThreadPool(int)建立的是有界執行緒池,也就是池中的執行緒個數可以指定最大數量。 建立專案Executors_3。類MyRunnable.java程式碼如下:package com.yc.executors_1;
public class MyRunnable implements Runnable{
private String userName;
public MyRunnable(String userName){
this.userName = userName;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " - userName=" + userName + " - begin:" + System.currentTimeMillis());
Thread.sleep(2 * 1000);
System.out.println(Thread.currentThread().getName() + " - userName=" + userName + " - end:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
類TPNewFixedThreadPooIntTest.java程式碼如下:
package com.yc.executors_1;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TPNewFixedThreadPoolIntTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for(int i = 0; i < 5; i ++){
executorService.execute(new MyRunnable( (i+1) + ""));
}
}
}
測試結果如下:
pool-1-thread-1 - userName=1 - begin:1490520507288
pool-1-thread-3 - userName=3 - begin:1490520507288
pool-1-thread-2 - userName=2 - begin:1490520507288
pool-1-thread-2 - userName=2 - end:1490520509289
pool-1-thread-3 - userName=3 - end:1490520509289
pool-1-thread-2 - userName=4 - begin:1490520509289
pool-1-thread-3 - userName=5 - begin:1490520509289
pool-1-thread-1 - userName=1 - end:1490520509289
pool-1-thread-3 - userName=5 - end:1490520511289
pool-1-thread-2 - userName=4 - end:1490520511289
可以看到池中最多可允許有三個執行緒同時線上,當thread-2和thread-3 end後立馬接著執行。
TP_5:使用newFixedThreadPool(int, ThreadFactory)定製執行緒工廠
有界執行緒池中的Thread類還可以有程式設計師自己定製,方法newFixedThreadPool(int nThread, ThreadFactory threadFactory)就是解決這個問題的。
建立專案newFixedThreadPoolFactory,建立MyThreadFactory.java執行緒工廠類程式碼如下:package com.yc.executors_2;
import java.util.concurrent.ThreadFactory;
public class MyThreadFactory implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
Thread mThread = new Thread(r);
mThread.setName("定製的有界執行緒工廠->" + Math.random());
return mThread;
}
}
測試類TPNewFixedThreadPoolFactoryTest.java 程式碼如下:package com.yc.executors_2;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TPNewFixThreadPoolFactoryTest {
public static void main(String[] args) {
MyThreadFactory threadFactory = new MyThreadFactory();
ExecutorService executorService = Executors.newFixedThreadPool(3, threadFactory);
for(int i = 5; i > 0; i --){
executorService.execute(new Runnable(){
@Override
public void run() {
System.out.println("我正在執行-" +Thread.currentThread().getName() );
}
});
}
}
}
得到某一次的測試結果如下:
我正在執行-定製的有界執行緒工廠->0.34551172025115573
我正在執行-定製的有界執行緒工廠->0.7745731609040991
我正在執行-定製的有界執行緒工廠->0.6848389479731579
我正在執行-定製的有界執行緒工廠->0.7745731609040991
我正在執行-定製的有界執行緒工廠->0.34551172025115573
TP_6:使用newSingleThreadExecutor()方法建立單一執行緒池
使用newSingleThreadExecutor()方法可以建立單一執行緒池。單一執行緒池可以實現以佇列的方式來執行任務。 建立專案Executors_4,類MyRunnable.java程式碼如下:package com.yc.executors_3;
public class MyRunnable implements Runnable{
private String StringName;
public MyRunnable(String StringName){
this.StringName = StringName;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " and - StringName=" + StringName + " -begin-> " + System.currentTimeMillis());
Thread.sleep(1* 1000);
System.out.println(Thread.currentThread().getName() + " and - StringName=" + StringName + " -end-> " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
類TPNewSingleThreadExecutorTest.java程式碼如下:
package com.yc.executors_3;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TPNewSingleThreadExecutorTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for(int i = 0; i < 3; i ++){
executorService.execute(new MyRunnable( "" + (i + 1)));
}
}
}
測得某一次的結果如下:pool-1-thread-1 and - StringName=1 -begin-> 1490522664356
pool-1-thread-1 and - StringName=1 -end-> 1490522665356
pool-1-thread-1 and - StringName=2 -begin-> 1490522665356
pool-1-thread-1 and - StringName=2 -end-> 1490522666356
pool-1-thread-1 and - StringName=3 -begin-> 1490522666356
pool-1-thread-1 and - StringName=3 -end-> 1490522667356
最多隻有一個執行緒在執行!!!。
TP7:使用newSingleThreadExecutor(ThreadFactory)定製執行緒工廠單一執行緒池
此方法的使用和前面的newFixedThreadPool(int, ThreadFactory)相似。
相關推薦
使用Executors工廠類建立執行緒池
介面Executor僅僅是一種規範,是一種宣告,是一種定義,並沒有實現任何的功能,所以大多數的情況下,需要使用介面的實現類來完成指定的功能,比如ThreadPoolExecutor類就是Executor的實現類,但ThreadPoolExecutor在使用上並不是那麼方便,
java併發程式設計--Executor框架以及Executors類的建立執行緒池方法
Eexecutor作為靈活且強大的非同步執行框架,其支援多種不同型別的任務執行策略,提供了一種標準的方法將任務的提交過程和執行過程解耦開發,基於生產者-消費者模式,其提交任務的執行緒相當於生產者,執行任務的執行緒相當於消費者,並用Runnab
Java 多執行緒池ThreadPoolExecutor解析及Executors類中提供的靜態方法來建立執行緒池
上面的程式碼可能看起來不是那麼容易理解,下面我們一句一句解釋: 首先,判斷提交的任務command是否為null,若是null,則丟擲空指標異常; 接著是這句,這句要好好理解一下: if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(c
為什麼不推薦通過Executors直接建立執行緒池
通過Executors的方法創建出來的執行緒池都實現了ExecutorSerivice介面。常用的方法有 newFixedThreadPool(int Threads):建立固定數目的執行緒池。 newSingleThreadPoolExecutor():建立一個單執行緒化的Executor n
一、Executors建立執行緒池
總結 Java中建立執行緒池很簡單,只需要呼叫Executors中相應的靜態方法即可,比如Executors.newFixedThreadPool(int nThreads),但是便捷不僅隱藏了複雜性,也為我們埋下了潛在的隱患(OOM,執行緒耗盡)。 Execu
通過Executors建立執行緒池存在的弊端,如何使用ThreadPoolExecutor建立執行緒池
Java通過Executors提供四種執行緒池,分別為:1)newCachedThreadPool 建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
不推薦使用Executors建立執行緒池,推薦通過ThreadPoolExecutor方式建立
執行緒池不允許使用Executors去建立,而是通過ThreadPoolExecutor的方式,這樣的處理方式讓寫的同學更加明確執行緒池的執行規則,規避資源耗盡的風險。 說明:Executors各個方法的弊端: 1)newFixedThreadPool和newSingleThreadExecut
區域性變數Executors建立執行緒池後一定要關閉
參考: http://curious.iteye.com/blog/2298849 網上有很多Executors的例子,但有些寫的非常草率,都只是寫如何建立,但有些沒有附上關閉方法。 Executors作為區域性變數時,建立了執行緒,一定要記得呼叫executor
java執行緒池優化,不再使用Executors建立執行緒池
今天在使用之前的執行緒池工具的時候,阿里的程式碼規範外掛提示不要這樣建立執行緒池。看了外掛做出的說明決定將執行緒池工具改為如下: import com.google.common.util.concurrent.ThreadFactoryBuilder; i
為什麼阿里Java規約禁止使用Java內建Executors建立執行緒池?
IDEA匯入阿里規約外掛,當你這樣寫程式碼時,外掛就會自動監測出來,並給你紅線提醒。 告訴你手動建立執行緒池,效果會更好。 在探祕原因之前我們要先了解一下執行緒池 ThreadPoolExecutor 都有哪些引數及其意義。 ThreadPoolExecutor 構造方法: publ
【搞定面試官】你還在用Executors來建立執行緒池?會有什麼問題呢?
前言 上文我們介紹了JDK中的執行緒池框架Executor。我們知道,只要需要建立執行緒的情況下,即使是在單執行緒模式下,我們也要儘量使用Executor。即: ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1); //此處不該
為什麼儘量不要使用Executors建立執行緒池
看阿里巴巴開發手冊併發程式設計這塊有一條:執行緒池不允許使用Executors去建立,而是通過ThreadPoolExecutor的方式,通過原始碼分析禁用的原因。 執行緒池的優點 管理一組工作執行緒,通過執行緒池複用執行緒有以下幾點優點: 減少資源建立:減少記憶體開銷,建立執行緒佔用記憶體 降低系統開銷:
阿里不允許使用 Executors 建立執行緒池!那怎麼使用,怎麼監控?
![](https://img-blog.csdnimg.cn/20201217014759355.jpg) 作者:小傅哥 部落格:[https://bugstack.cn](https://bugstack.cn) >沉澱、分享、成長,讓自己和他人都能有所收穫!
如何在JAVA中建立執行緒池
ExecutorService 今天小編要分享的是關於執行緒池, 想必接觸到併發處理的朋友都有用到執行緒池, 當我們訪問伺服器的量達到伺服器一定量的時候, 比如幾百萬幾千萬,很容易造成伺服器崩掉, 如果使用執行緒進行併發處理,將使用的執行緒進行回收在使用,就減小了伺服器的壓力
JAVA Executor框架建立執行緒池
為了更好的控制多執行緒,JDK提供理論一套執行緒框架Executor,幫助開發人員有效的進行執行緒控制。它們都在java.util.concurrent包中,是JDK併發包的核心。其中有一個比較重要的類:Executors,他扮演著執行緒工廠的角色,我們通過Executors可以建立特定功能的執行緒
建立執行緒池的方式
Executors 工具型別。為Executor執行緒池提供工具方法。可以快速的提供若干種執行緒池。如:固定容量的,無限容量的,容量為1等各種執行緒池。 執行緒池是一個程序級的重量級資源。預設的生命週期和JVM一致。當開啟執行緒池後,直到JVM關閉為止,是執行緒池的預設生命週期。如果手工呼叫shutdow
Android建立執行緒池
在一個龐大的android程式中,避免不了使用耗時操作,這些操作必須寫到子執行緒中,因為如果在android系統設定的是在5秒內,android系統沒有響應的話,就會報錯ANR(程式無響應)的錯誤,隨著android的程式的功能越來越多,使用的子執行緒也越來越多,那麼android就引入了一個執
java 多執行緒之利用Thread類建立執行緒(Day02)
前言:在一個程式中,如果一次只完成一件事情,很容易實現,但現實生活中很多事情都是同時進行的,所以在java中為了模擬這種狀態,引入了執行緒機制,簡單的說,當程式同時完成很多事情時,就是所謂的多執行緒。 實現執行緒的兩種方式:一是通過繼承Thread類來建立執行緒,另一種方法
jdk執行緒池總類以及執行緒池的核心引數簡述
JDK自帶執行緒池總類: 1、newFixedThreadPool建立一個指定工作執行緒數量的執行緒池。每當提交一個任務就建立一個工作執行緒,如果工作執行緒數量達到執行緒池初始的最大數,則將提交的任務存入到池佇列中。 2、newCachedThreadPool建立一個可快
JAVA多執行緒機制第二彈:(程式碼)Thread的子類建立執行緒
在Java中,執行緒物件的建立是用Threa類或者它的子類建立。 在編寫Thread類的子類時,需要重寫父類的run()方法,其目的是規定執行緒的具體操作,否則執行緒就沒有開始的地方 在這裡,做一個小小總結: ··線上程的編寫的時候,要重寫父類的run()方法,在ru