什么是线程池
多线程开发中,由于线程数量多,并且每个线程执行一段时间就结束,所以要频繁的创建线程,但是这样频繁的创建线程会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。在这种情况下,人们就想要一种可以线程执行完后不用销毁,同时该线程还可以去执行其他任务,在这样的情况下线程池就出现了。
线程池就是线程的池子,任务提交到线程池后,就从线程池中取出一个空闲的线程为之服务,服务完后不销毁该线程,而是将该线程还回到线程池中。
在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,如果没有空闲的进程,任务就处于等待状态,这就是封装。
使用了线程池后减少了创建和销毁线程的次数,每个线程都可以被重复利用,可执行多个任务;同时可以根据系统的承受能力,调整线程池中线程的数目,避免出现将系统内存消耗完毕这样的情况出现。
ThreadPoolExecuto例子
我们先通过一个简单的线程池的例子先来对ThreadPoolExecuto进行一个整体的认识,我们构造了一个正常线程数量为5,最大线程池数量为10,任务缓存队列5的线程池,让这个线程池来执行15个任务的demo。
先来看下MyRunnable类,用来记录当前正在执行的任务数:
- 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 + "执行完毕");
- }
- }
线程池客户端:
- 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();
- }
- }
执行结果:
- 正在执行的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执行完毕
通过这个demo应该可以对线程池有了一个宏观的理解了吧,下面我们就继续深入的来学习ThreadPoolExecutor 对象。