Java中有幾種線程池?使用線程池有什麼風險?

Java裏面線程池的頂級接口是Executor,但是嚴格意義上講Executor並不是一個線程池,而只是一個執行線程的工具,它真正的線程池接口是ExecutorService。

使用線程池能夠爲了防止資源不足,因爲頻繁創建和銷燬線程會消耗大量資源,尤其是當線程執行時間>線程創建時間+線程銷燬時間,此時會堆積大量線程。Java中,創建線程池有四種方式,如下:

1)newCachedThreadPool()
創建一個可緩存線程池,線程池爲無限大,如果線程池長度超過處理需要,可靈活回收空閒線程,即當執行當前任務時上一個任務已經完成,會複用執行上一個任務的線程,而不用每次新建線程;如果上一個線程沒有結束則會新建線程。

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

public class CachedThreadPool {
	private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

	public static void main(String args[]) {
		for (int i = 0; i < 10; i++) {
			try {
				if (i == 4) {
					Thread.sleep(2000);
				}
			} catch (Exception e) {
				e.getStackTrace();
			}
			cachedThreadPool.execute(new Runnable() {
				public void run() {
					try {
						Thread.sleep(1000);
					} catch (Exception e) {
						e.getStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在被執行");
				}
			});
		}
	}
	/**
	 * 執行結果如下(console輸出): 
	 * pool-1-thread-1正在被執行 
	 * pool-1-thread-4正在被執行
	 * pool-1-thread-3正在被執行 
	 * pool-1-thread-2正在被執行 
	 * pool-1-thread-4正在被執行
	 * pool-1-thread-1正在被執行 
	 * pool-1-thread-3正在被執行 
	 * pool-1-thread-2正在被執行
	 * pool-1-thread-5正在被執行 
	 * pool-1-thread-6正在被執行
	 */
}

在i=5的時候,需停留2秒,此時線程1-4都已經釋放,所以1-4線程可以複用,這就是newCachedThreadPool()線程池的優點。

2)newFixedThreadPool()
可重用固定個數的線程池,噹噹前線程數大於總線程數時會進行等待,等待線程池內的線程執行完,相對來說佔用內存少,因爲如果等待線程數量過多,也是相對耗廢資源的。

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

public class FixedThreadPool {
	private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);

	public static void main(String args[]) {
		for (int i = 0; i < 10; i++) {
			fixedThreadPool.execute(new Runnable() {
				public void run() {
					System.out.println(Thread.currentThread().getName() + "正在被執行");
					try {
						Thread.sleep(1000);
					} catch (Exception e) {
						e.getStackTrace();
					}
				}
			});
		}
	}
}

線程池大小爲4,所以如果線程執行數量超過4則會進行等待,所以newFixedThreadPool()的缺點也很明顯,就是如果線程池數量設置明顯過小,則會導致大量線程等待,造成資源浪費。

3)newSingleThreadExecutor()
單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO,優先級)執行,如果該線程異常結束,會有另一個線程取代它,保證順序執行。
所以缺點也很明顯,就是單線程執行,線程多,執行速度會比較慢。

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

public class SingleThreadPool {
	private static ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

	public static void main(String args[]) {
		for (int i = 0; i < 10; i++) {
			final int index = i;
			singleThreadPool.execute(new Runnable() {
				public void run() {
					try {
						System.out.println(Thread.currentThread().getName() + "正在執行 index=" + index);
						Thread.sleep(1000);
					} catch (Exception e) {
						e.getStackTrace();
					}
				}
			});
		}
	}
	/**
	 * 執行結果如下: 
	 * pool-1-thread-1正在執行 index=0 
	 * pool-1-thread-1正在執行 index=1
	 * pool-1-thread-1正在執行 index=2 
	 * pool-1-thread-1正在執行 index=3
	 * pool-1-thread-1正在執行 index=4 
	 * pool-1-thread-1正在執行 index=5
	 * pool-1-thread-1正在執行 index=6 
	 * pool-1-thread-1正在執行 index=7
	 * pool-1-thread-1正在執行 index=8 
	 * pool-1-thread-1正在執行 index=9
	 * 
	 * 結論:所有的線程都是線程1來執行而且是有序執行,這就是單線程池!
	 */
}

4)newScheduledThreadPool()
可重用固定個數的線程池,當前線程數大於總數則會進行等待,並且可以設置線程延遲執行時間。

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPool {
	private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);

	public static void main(String args[]) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmsssss");

		for (int i = 0; i < 10; i++) {
			System.out.println(i + "開始執行時間" + sdf.format(new Date()));
			scheduledThreadPool.schedule(new Runnable() {
				public void run() {
					System.out.println(Thread.currentThread().getName() + "正在執行 執行時間=" + sdf.format(new Date()));
				}
			}, 3, TimeUnit.SECONDS);
		}
	}
}

那麼,使用線程池有沒有什麼風險呢?

1)死鎖:任何的多線程都有可能發生死鎖的風險(線程之間互相等待)

2)資源不足:線程池太大造成,正常來說合理創建線程池大小一般不會出現這個問題

3)線程泄漏和請求過載
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章