您的位置:首页 > 其它

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 对象。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程池