1. 程式人生 > >Java ExecutorService四種執行緒池基本介紹以及相關舉例

Java ExecutorService四種執行緒池基本介紹以及相關舉例

1、new Thread的弊端

執行一個非同步任務你還只是如下new Thread嗎?

new Thread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
    }
}).start();

那你就out太多了,new Thread的弊端如下:
a. 每次new Thread新建物件效能差。
b. 執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致宕機或oom。
c. 缺乏更多功能,如定時執行、定期執行、執行緒中斷。
相比new Thread,Java提供的四種執行緒池的好處在於:
a. 重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。
b. 可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
c. 提供定時執行、定期執行、單執行緒、併發數控制等功能。

2、Java 執行緒池
Java通過Executors提供四種執行緒池,分別為:
newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。
newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。

3、以下例子是我在公司編寫程式碼時所執行的基本方案

package com.shuang.executorservice;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * ExecutorService執行緒池的使用
 * 這裡只是執行了一個執行緒的任務為例
 * @author shuang
 *
 */
public class ExecutorServiceTest {
	
	//執行緒執行後需要得到的結果之一
	private String strString = null;
	//例項化
	private static ExecutorServiceTest INSTANCE = new ExecutorServiceTest();
	
	//獲取單例項
	public static ExecutorServiceTest getInstance(){
		return INSTANCE;
	} 
	
	//構造方法私有化
	private ExecutorServiceTest(){
		
		
		ExecutorService executor = null;
		try {
			executor = Executors.newFixedThreadPool(3, new SelfThreadFactory("shuang-thread"));

			Future<String> future = executor.submit(new TestTask());
			
			strString = future.get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}finally {
			if(executor != null){
				executor.shutdown();
			}
		}
	}
	public String getStrString(){
		return strString;
	}
	
	

}
package com.shuang.executorservice;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * 執行緒工廠
 * @author shuang
 *
 */
public class SelfThreadFactory implements ThreadFactory {
	//執行緒組
	private final ThreadGroup group;
	//可以使用院子方式更新的int值。有關院子變數屬性的描述
	private final AtomicInteger threadNumber = new AtomicInteger(1);
	//執行緒名字首
	private final String namePrefix;
	
	/**
	 * 構造器
	 * @param name 執行緒名
	 */
	public SelfThreadFactory(String name) {
		//安全管理器,相關介紹可以看APi文件
		SecurityManager securityManager = System.getSecurityManager();
		group = securityManager == null?Thread.currentThread().getThreadGroup():securityManager.getThreadGroup();
		namePrefix = new StringBuilder().append(name).append("-").toString();
	}

	@Override
	public Thread newThread(Runnable target) {
		//分配新的Thread物件,以便將target作為其中執行物件。
		//將指定的name作為其名稱,作為group所引用的執行緒組的一員,並具有指定的堆疊大小
		
		Thread thread =new Thread(
				group, 
				target, 
				new StringBuilder().append(namePrefix).append(threadNumber.getAndIncrement()).toString(), 
				0);
		if(thread.isDaemon()){//守護執行緒
			thread.setDaemon(false);
		}
		if(thread.getPriority() != 5){//優先順序
			thread.setPriority(5);
		}
		return thread;
	}

}
package com.shuang.executorservice;

import java.util.concurrent.Callable;
/**
 * 測試任務類-其中一個
 * @author shuang
 *
 */
public class TestTask implements Callable<String> {

	@Override
	public String call() throws Exception {
		return "this is OK!";
	}


}
package com.shuang.executorservice;
//測試類
public class Test {
	public static void main(String[] args) {
		System.out.println(ExecutorServiceTest.getInstance().getStrString());
	}
}