您的位置:首页 > 其它

线程6-线程池

2015-12-22 16:40 288 查看
1、几个概念:
(1)线程池 ThreadPoolExecutor:存放线程的池子( --!)
(2)线程 Thread:用于执行实现<Runnable>接口的任务
(3)任务缓存队列:用于存放Thread要执行的任务
2、几个变量和方法的解释
(1)ThreadPoolExecutor的构造方法参数
corePoolSize:核心池的大小,在创建了线程池后,默认情况下,线程数为0。当有任务来了之后,就创建一个线程
去执行任务,当线程池中的线程数达到corePoolSize之后,就会尝试把新到达的任务放到缓存队列中
maximumPoolSize:线程池中最大线程数
keepAliveTime:线程池中的某个线程在多久没有执行任务时,线程会终止
unit:参数keepAliveTime的时间单位,有7种取值,参见TimeUnit类
workQueue:一个阻塞队列,用来存储等待执行的**任务**(非线程),阻塞队列有以下几种选择
一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
(2)execute()方法,可向线程池提交一个任务,交由线程池去执行
(3)submit()方法,也是向线程池提交一个任务,它能够返回任务结果,看源码可知,
其实submit()也是调用了execute,只不过它使用了RunnableFutureo类来获取线程执行结果
(4)shutdown(),等所有任务执行完毕后,关闭线程池
(5)shutdownNow(),马上关闭线程池,不管任务是否完成
(6)拒绝策略,通常有以下4种策略
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
(7)任务缓存队列及排队策略
任务缓存策略,即workQueue,用来等待任务执行的任务
workQueue通常有以下3种类型
1)ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
2)LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE(0x7fffffff);
3)synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
(8)在ThreadPoolExecutor类中定义了一个volate变量,用来指示线程池状态,线程池有4种状态
1)static final int RUNNING = 0;
2)static final int SHUTDOWN = 1;
3)static final int STOP = 2;
4)static final int TERMINATED = 3;
创建后,线程池处于RUNNING状态
shutdown()后,线程处于SHUTDOWN状态,此时它只等待所有线程执行完任务,不接受新任务
shotdownNow()后,线程处于STOP状态,它不接受任务,尝试终止正在执行的任务
线程池处于STOP状态后,并且所有工作线程已销毁,任务缓存队列已清空或执行结束后,线程池被置为TERMINATED(结束)状态
3、线程池的工作流程
创建线程池(ThreadPoolExecutor)时,会指定核心池(corePoolSize)和线程池的最大线程容量(maximumPoolSize)
(1)创建线程池,线程池中线程为0,任务缓存队列中的任务为0
(2)ThreadPoolExecutor对象使用execute方法,向线程池提交一个任务
(3)线程池拿到任务,进行判断
如果当前线程池中的线程数,=<corePoolSize,创建一个新线程去执行任务
如果当前线程池中的线程数,大于corePoolSize并且小于maximumPoolSize,
则线程池会尝试把任务放到任务缓存队列,
如果放入缓存队列失败(一般来说是任务缓存队列已满),线程池尝试创建线程来执行任务
放入缓存队列成功,任务就等待空闲线程来取出执行
如果当前线程池中的线程数,等于maximunPoolSize,
则线程池会尝试把任务放到任务缓存队列,
如果放入缓存队列成功,任务就等待空闲线程来取出执行
如果放入缓存队列失败(一般来说是任务缓存队列已满),则会采取拒绝策略进行处理
4、线程池例子

package com.线程池;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test {
public void testThread() throws InterruptedException {

/**线程池构造方法中
*  public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
(1)corePoolSize:核心池的大小,在创建了线程池后,默认情况下,线程数为0当有任务来了之后,就创建一个线程
去执行任务,当线程池中的线程数达到corePoolSize之后,就会把新到达的任务放到缓存队列中
(2)maximumPoolSize:线程中最大线程数
(3)keepAliveTime:线程池中的某个线程在多久没有执行任务时,会终止
(4)unit:参数keepAliveTime的时间单位,有7种取值,参见TimeUnit类
(5)workQueue:一个阻塞队列,用来存储等待执行的**任务**(非线程),阻塞队列有以下几种选择:
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
ArrayBlockingQueue和PriorityBlockingQueue使用较少,
一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
*/
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(6));//参数6是阻塞队列的容量

//执行任务
for(int i = 0 ; i < 15 ; i ++){
MyMask mask = new MyMask(i);
/**
* ThreadPoolExecutor的四个方法
* (1)execute()方法,可向线程池提交一个任务,交由线程池去执行
* (2)submit()方法,也是向线程池提交一个任务,它能够返回任务结果,看源码可知,
*     其实submit()也是调用了execute,只不过它使用了RunnableFutureo类来获取线程执行结果
* (3)shutdown(),等所有任务执行完毕后,关闭线程池
* (4)shutdownNow(),马上关闭线程池,不管任务是否完成
*/

executor.execute(mask);
System.out.println("线程池中的线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数:"+executor.getQueue().size()
+",已执行完的任务数:"+executor.getCompletedTaskCount());
//Thread.currentThread();
//Thread.sleep(2000);
}
executor.shutdown();

}
public static void main(String[] args) {
Test test = new Test();
try {
test.testThread();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

class MyMask implements Runnable{
private Integer intNum;

public MyMask(int num){
this.intNum = num;
}

@Override
public void run() {
System.out.println("正在执行task "+intNum);

Thread.currentThread();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("task "+intNum+"执行完成");

}

}


参考:http://www.cnblogs.com/dolphin0520/p/3932921.html 原文写的很棒,讲的非常清晰,这篇博客是我按照自己的理解方式,重新整理了一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: