ThreadPoolExecutor
2015-07-28 22:02
169 查看
什么是线程池
多线程开发中,由于线程数量多,并且每个线程执行一段时间就结束,所以要频繁的创建线程,但是这样频繁的创建线程会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。在这种情况下,人们就想要一种可以线程执行完后不用销毁,同时该线程还可以去执行其他任务,在这样的情况下线程池就出现了。
线程池就是线程的池子,任务提交到线程池后,就从线程池中取出一个空闲的线程为之服务,服务完后不销毁该线程,而是将该线程还回到线程池中。
在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,如果没有空闲的进程,任务就处于等待状态,这就是封装。
使用了线程池后减少了创建和销毁线程的次数,每个线程都可以被重复利用,可执行多个任务;同时可以根据系统的承受能力,调整线程池中线程的数目,避免出现将系统内存消耗完毕这样的情况出现。
ThreadPoolExecuto例子
我们先通过一个简单的线程池的例子先来对ThreadPoolExecuto进行一个整体的认识,我们构造了一个正常线程数量为5,最大线程池数量为10,任务缓存队列5的线程池,让这个线程池来执行15个任务的demo。
先来看下MyRunnable类,用来记录当前正在执行的任务数:
[java] view
plaincopy
package com.tgb.threadpool;
/**
* 线程执行
* @author kang
*
*/
public class MyRunnable implements Runnable {
// 正在执行的任务数
private int num;
public MyRunnable(int num) {
this.num = num;
}
@Override
public void run() {
System.out.println("正在执行的MyRunnable " + num);
try {
Thread.currentThread().sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("MyRunnable " + num + "执行完毕");
}
}
线程池客户端:
[java] view
plaincopy
package com.tgb.threadpool;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 线程池调用客户端
* @author kang
*
*/
public class ThreadPoolExecutorTest {
//池中所保存的线程数,包括空闲线程。
final static int corePoolSize = 5;
//池中允许的最大线程数。
final static int maximumPoolSize = 10;
//当线程数大于核心线程时,此为终止前多余的空闲线程等待新任务的最长时间
final static long keepAliveTime = 200;
//执行前用于保持任务的队列5,即任务缓存队列
final static ArrayBlockingQueue<Runnable> workQueue =new ArrayBlockingQueue<Runnable>(5);
public static void main(String[] args) {
//构建一个线程池,正常线程数量为5,最大线程数据为10,等待时间200
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES, workQueue);
//线程池去执行15个任务
for (int i = 0; i < 15; i++) {
MyRunnable myRunnable = new MyRunnable(i);
threadPoolExecutor.execute(myRunnable);
System.out.println("线程池中现在的线程数目是:"+threadPoolExecutor.getPoolSize()+", 队列中正在等待执行的任务数量为:"+
threadPoolExecutor.getQueue().size());
}
//关掉线程池
threadPoolExecutor.shutdown();
}
}
执行结果:
[cpp] view
plaincopy
正在执行的MyRunnable 0
线程池中现在的线程数目是:1, 队列中正在等待执行的任务数量为:0
线程池中现在的线程数目是:2, 队列中正在等待执行的任务数量为:0
正在执行的MyRunnable 1
线程池中现在的线程数目是:3, 队列中正在等待执行的任务数量为:0
正在执行的MyRunnable 2
线程池中现在的线程数目是:4, 队列中正在等待执行的任务数量为:0
正在执行的MyRunnable 3
线程池中现在的线程数目是:5, 队列中正在等待执行的任务数量为:0
正在执行的MyRunnable 4
线程池中现在的线程数目是:5, 队列中正在等待执行的任务数量为:1
线程池中现在的线程数目是:5, 队列中正在等待执行的任务数量为:2
线程池中现在的线程数目是:5, 队列中正在等待执行的任务数量为:3
线程池中现在的线程数目是:5, 队列中正在等待执行的任务数量为:4
线程池中现在的线程数目是:5, 队列中正在等待执行的任务数量为:5
线程池中现在的线程数目是:6, 队列中正在等待执行的任务数量为:5
正在执行的MyRunnable 10
线程池中现在的线程数目是:7, 队列中正在等待执行的任务数量为:5
正在执行的MyRunnable 11
线程池中现在的线程数目是:8, 队列中正在等待执行的任务数量为:5
正在执行的MyRunnable 12
线程池中现在的线程数目是:9, 队列中正在等待执行的任务数量为:5
正在执行的MyRunnable 13
线程池中现在的线程数目是:10, 队列中正在等待执行的任务数量为:5
正在执行的MyRunnable 14
MyRunnable 0执行完毕
正在执行的MyRunnable 5
MyRunnable 3执行完毕
MyRunnable 4执行完毕
MyRunnable 2执行完毕
正在执行的MyRunnable 7
正在执行的MyRunnable 6
正在执行的MyRunnable 8
MyRunnable 1执行完毕
正在执行的MyRunnable 9
MyRunnable 12执行完毕
MyRunnable 11执行完毕
MyRunnable 10执行完毕
MyRunnable 14执行完毕
MyRunnable 13执行完毕
MyRunnable 5执行完毕
MyRunnable 9执行完毕
MyRunnable 8执行完毕
MyRunnable 6执行完毕
MyRunnable 7执行完毕
从执行结果来看,当线程池中线程的数量大于5时,便将任务放入任务缓存队列里面,任务缓存队列满了以后,变创建新的线程,来执行,如果让任务数量大于15,程序就会报错,抛出任务拒绝异常,这时可以增大任务缓存队列,有兴趣的同学可以去试试。
通过这个demo应该可以对线程池有了一个宏观的理解了吧,下面我们就继续深入的来学习ThreadPoolExecutor 对象。