1. 程式人生 > >JDK1.5中的執行緒池(java.util.concurrent.ThreadPoolExecutor)使用簡介

JDK1.5中的執行緒池(java.util.concurrent.ThreadPoolExecutor)使用簡介

在多執行緒大師Doug Lea的貢獻下,在JDK1.5中加入了許多對併發特性的支援,例如:執行緒池。

一、簡介
執行緒池類為 java.util.concurrent.ThreadPoolExecutor,常用構造方法為:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)

corePoolSize: 執行緒池維護執行緒的最少數量
maximumPoolSize:執行緒池維護執行緒的最大數量
keepAliveTime: 執行緒池維護執行緒所允許的空閒時間
unit: 執行緒池維護執行緒所允許的空閒時間的單位
workQueue: 執行緒池所使用的緩衝佇列
handler: 執行緒池對拒絕任務的處理策略

一個任務通過 execute(Runnable)方法被新增到執行緒池,任務就是一個 Runnable型別的物件,任務的執行方法就是 Runnable型別物件的run()方法。

當一個任務通過execute(Runnable)方法欲新增到執行緒池時:

如果此時執行緒池中的數量小於corePoolSize,即使執行緒池中的執行緒都處於空閒狀態,也要建立新的執行緒來處理被新增的任務。

如果此時執行緒池中的數量等於 corePoolSize,但是緩衝佇列 workQueue未滿,那麼任務被放入緩衝佇列。

如果此時執行緒池中的數量大於corePoolSize,緩衝佇列workQueue滿,並且執行緒池中的數量小於maximumPoolSize,建新的執行緒來處理被新增的任務。

如果此時執行緒池中的數量大於corePoolSize,緩衝佇列workQueue滿,並且執行緒池中的數量等於maximumPoolSize,那麼通過 handler所指定的策略來處理此任務。

也就是:處理任務的優先順序為:
核心執行緒corePoolSize、任務佇列workQueue、最大執行緒maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。

當執行緒池中的執行緒數量大於 corePoolSize時,如果某執行緒空閒時間超過keepAliveTime,執行緒將被終止。這樣,執行緒池可以動態的調整池中的執行緒數。

unit可選的引數為java.util.concurrent.TimeUnit中的幾個靜態屬性:
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。

workQueue我常用的是:java.util.concurrent.ArrayBlockingQueue

handler有四個選擇:
ThreadPoolExecutor.AbortPolicy()
丟擲java.util.concurrent.RejectedExecutionException異常
ThreadPoolExecutor.CallerRunsPolicy()
重試添加當前的任務,他會自動重複呼叫execute()方法
ThreadPoolExecutor.DiscardOldestPolicy()
拋棄舊的任務
ThreadPoolExecutor.DiscardPolicy()
拋棄當前的任務


二、一般用法舉例
//------------------------------------------------------------
//TestThreadPool.java
//package cn.simplelife.exercise;

import java.io.Serializable;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThreadPool {

private static int produceTaskSleepTime = 2;
private static int consumeTaskSleepTime = 2000;
private static int produceTaskMaxNumber = 10;

public static void main(String[] args) {

//構造一個執行緒池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.DiscardOldestPolicy());

for(int i=1;i<=produceTaskMaxNumber;i++){
try {
//產生一個任務,並將其加入到執行緒池
String task = "[email protected] " + i;
System.out.println("put " + task);
threadPool.execute(new ThreadPoolTask(task));

//便於觀察,等待一段時間
Thread.sleep(produceTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* 執行緒池執行的任務
* @author hdpan
*/
public static class ThreadPoolTask implements Runnable,Serializable{
private static final long serialVersionUID = 0;
//儲存任務所需要的資料
private Object threadPoolTaskData;

ThreadPoolTask(Object tasks){
this.threadPoolTaskData = tasks;
}
public void run(){
//處理一個任務,這裡的處理方式太簡單了,僅僅是一個列印語句
System.out.println("start .."+threadPoolTaskData);
try {
////便於觀察,等待一段時間
Thread.sleep(consumeTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
threadPoolTaskData = null;
}
public Object getTask(){
return this.threadPoolTaskData;
}
}
}
//------------------------------------------------------------
說明:
1、在這段程式中,一個任務就是一個Runnable型別的物件,也就是一個ThreadPoolTask型別的物件。

2、一般來說任務除了處理方式外,還需要處理的資料,處理的資料通過構造方法傳給任務。

3、在這段程式中,main()方法相當於一個殘忍的領導,他派發出許多工,丟給一個叫 threadPool的任勞任怨的小組來做。

這個小組裡面隊員至少有兩個,如果他們兩個忙不過來,任務就被放到任務列表裡面。

如果積壓的任務過多,多到任務列表都裝不下(超過3個)的時候,就僱傭新的隊員來幫忙。但是基於成本的考慮,不能僱傭太多的隊員,至多隻能僱傭 4個。

如果四個隊員都在忙時,再有新的任務,這個小組就處理不了了,任務就會被通過一種策略來處理,我們的處理方式是不停的派發,直到接受這個任務為止(更殘忍!呵呵)。

因為隊員工作是需要成本的,如果工作很閒,閒到 3SECONDS都沒有新的任務了,那麼有的隊員就會被解僱了,但是,為了小組的正常運轉,即使工作再閒,小組的隊員也不能少於兩個。

4、通過調整 produceTaskSleepTime和 consumeTaskSleepTime的大小來實現對派發任務和處理任務的速度的控制,改變這兩個值就可以觀察不同速率下程式的工作情況。

5、通過調整4中所指的資料,再加上調整任務丟棄策略,換上其他三種策略,就可以看出不同策略下的不同處理方式。

6、對於其他的使用方法,參看jdk的幫助,很容易理解和使用。

相關推薦

JDK1.5執行(java.util.concurrent.ThreadPoolExecutor)使用簡介

在多執行緒大師Doug Lea的貢獻下,在JDK1.5中加入了許多對併發特性的支援,例如:執行緒池。 一、簡介執行緒池類為 java.util.concurrent.ThreadPoolExecutor,常用構造方法為:ThreadPoolExecutor(int corePoolSize, int ma

[引用]java執行學習-java.util.concurrent詳解(四) BlockingQueue

自:http://janeky.iteye.com/blog/7706717.BlockingQueue     “支援兩個附加操作的 Queue,這兩個操作是:獲取元素時等待佇列變為非空,以及儲存元素時等待空間變得可用。“     這裡我們主要討論BlockingQueue的最典型實現:LinkedBlo

Java併發:多執行java.util.concurrent併發包總結

引言前面已經針對Java多執行緒框架中具體的點介紹了很多了,現在是需要一個概括性總結的時候了,正好從網上找到一張描述java.util.concurrent包組成結構的類圖,正好可以對java多執行緒中

java.util.concurrent執行Executors的使用

執行緒池的概念與Executors類的使用 (1)建立固定大小的執行緒池–當有多個任務時,會先按照執行緒池中的資料執行任務,其他任務處於等待過程中,等執行完這批任務後再執行下批任務。 (2)建立快

沉澱再出發:java執行解析

沉澱再出發:java中執行緒池解析 一、前言    在多執行緒執行的環境之中,如果執行緒執行的時間短但是啟動的執行緒又非常多,執行緒運轉的時間基本上浪費在了建立和銷燬上面,因此有沒有一種方式能夠讓一個執行緒執行完自己的任務之後又被重複使用呢?執行緒池的出現就是為了解決這個問題。到了現在

Java執行基本api及其作用

1.執行緒池相關的類 2.重要類的api及其方法 Executors.newCachedThreadPool() 建立一個可快取的執行緒池 Executors.newSingleThreadExecutor();建立一個只有一個執行緒執行的 不可修改的執行緒池  

Java執行及其實現類ThreadPoolExecutor

前言:像我們連線資料庫一樣,需要不斷地建立連線,銷燬連線,如果都是人為地一個個建立和銷燬的話會很費勁,所以就誕生了資料庫連線池,執行緒池的產生也是同樣的道理。 執行緒池預先建立了若干數量的執行緒,並且不能由使用者直接對執行緒的建立進行控制,在這個前提下重複使用固定或較為固定數目的執行緒來完成任務

java執行的生命週期

執行緒池生命週期包括: RUNNING:接收新的任務並處理佇列中的任務 SHUTDOWN:不接收新的任務,但是處理佇列中的任務 STOP:不接收新的任務,不處理佇列中的任務,同時中斷處理中的任務 TIDYING:所有的任務處理完成,有效的執行緒數是0 TERMINATED:termin

Java執行,你真的會用嗎

轉載自   Java中執行緒池,你真的會用嗎 在《深入原始碼分析Java執行緒池的實現原理》這篇文章中,我們介紹過了Java中執行緒池的常見用法以及基本原理。 在文中有這樣一段描述: 可以通過Executors靜態工廠構建執行緒池,但一般不建議這樣使用。 關於這個

java執行的生命週期與執行中斷

執行緒池生命週期包括: RUNNING:接收新的任務並處理佇列中的任務 SHUTDOWN:不接收新的任務,但是處理佇列中的任務 STOP:不接收新的任務,不處理佇列中的任務,同時中斷處理中的任務 TIDYING:所有的任務處理完成,有效的執行緒數是0 TE

Java執行,你真的瞭解會用嗎

在《 深入原始碼分析Java執行緒池的實現原理 》這篇文章中,我們介紹過了Java中執行緒池的常見用法以及基本原理。 在文中有這樣一段描述: 可以通過Executors靜態工廠構建執行緒池,但一般不建議這樣使用。 關於這個問題,在那篇文章中並沒有深入的展開。作者之所以這

Java執行,你真的會用嗎?

  我騎著小毛驢,喝著大紅牛哇,哩個啷格里格朗,別問我為什麼這木開心,如果活著不是為了浪蕩那將毫無意義      今天來捋一捋我們平日經常用的instanceof和typeof的一些小問題      typeof:      typeof裡面是由一個小坑的  我們今天著重來研

Java執行ThreadPoolExecutor原理探究

一、 前言 執行緒池主要解決兩個問題:一方面當執行大量非同步任務時候執行緒池能夠提供較好的效能,,這是因為使用執行緒池可以使每個任務的呼叫開銷減少(因為執行緒池執行緒是可以複用的)。另一方面執行緒池提供了一種資源限制和管理的手段,比如當執行一系列任務時候對執行緒的管理,每個ThreadPool

Java高併發程式設計(十一):Java執行

在開發過程中,合理地使用執行緒池能夠帶來3個好處。 降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。 提高響應速度。當任務到達時,任務可以不需要等到執行緒建立就能立即執行。 提高執行緒的可管理性。執行緒是稀缺資源,如果無限制地建立

java執行的幾種實現方式

1、執行緒池簡介:     多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。         假設一個伺服器完成一項任務所需時間為:T1 建立執行緒時間,T2 線上程中執行任務的時間,T3 銷燬執

java執行ExecutorService 執行管理

 程式碼: package com.bob.test; import java.util.concurrent.ExecutorService; import java.util.concurren

Java併發包執行ThreadPoolExecutor原理探究

一、執行緒池簡介   執行緒池的使用主要是解決兩個問題:①當執行大量非同步任務的時候執行緒池能夠提供更好的效能,在不使用執行緒池時候,每當需要執行非同步任務的時候直接new一個執行緒來執行的話,執行緒的建立和銷燬都是需要開銷的。而執行緒池中的執行緒是可複用的,不需要每次執行非同步任務的時候重新建立和銷燬執行

執行Java

為啥有的執行緒池? 在我們執行任務時,如果為每個任務建立一個新執行緒來執行的話,想想執行緒狀態:新建、就緒、執行、銷燬。這些都是需要消耗計算資源的;那麼就用一個執行緒池,放置一部分執行緒,讓他時刻處於執行狀態,執行任務結束後,將執行緒歸還執行緒池。這樣,是不是就可以避免了新建和銷燬的這兩步?

常見4執行

執行緒池能有效的處理多個執行緒的併發問題,避免大量的執行緒因為互相強佔系統資源導致阻塞現象,能夠有效的降低頻繁建立和銷燬執行緒對效能所帶來的開銷。真正執行緒池的實現是通過ThreadPoolExecutor,ThreadPoolExecutor通過配置不同的引數配置來建立執行緒池。下面簡單的介紹一下各個執行緒

Junit單元測試+aop+spring+執行,在進行Junit測試時切面執行內呼叫的方法不執行

一、問題背景: 寫了一個切面,指向某service包下的所有類及方法,當該service包下方法被呼叫時切面執行,切面中用了執行緒池ExecutorService pool = Executors.newFixedThreadPool(5);執行緒池內呼叫了dao層的方法。 二、問題描述:單