1. 程式人生 > >使用Executors工廠類建立執行緒池

使用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