线程池的简单使用

作者: 选一个昵称这么难 | 来源:发表于2017-09-01 18:23 被阅读168次

    1.什么是线程池

    线程池就是事先把多个线程放到一个容器中,当使用的时候不用new而是直接去线程池中拿即可,节省了开辟子线程的时间,提高代码执行效率。

    2.线程池的优点

    第一:降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗

    第二:提高响应速度,当任务到达时,任务可以不需要等到线程的创建就能执行

    第三:提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

    3.如何创建一个线程池

    /**
    * 项目中,线程池的管理类一般都是一个对象,所以这里用单例设计模式
     */
    public class ThreadPoolManager {
    private static ThreadPoolManager poolManager = new ThreadPoolManager();
    //核心线程的数量,表示可以同时有多少个线程在运行
    private int corePoolSize =Runtime.getRuntime().availableProcessors()*2+1;
    //线程池的大小,表示该线程池一共可以容得下多少个线程,超过这个数目就会根据策略来执行,
    // new ThreadPoolExecutor.AbortPolicy()一般用这个策略,表示抛弃
    private int maximumPoolSize=corePoolSize;
    //存活时间,表示在最大线程池中等待任务的线程的存活时间。
    private long keepAliveTime=5;
    //存活时间的单位
    private TimeUnit unit=TimeUnit.SECONDS;
    private ThreadPoolExecutor executor;
    
    //通过单例设计模式来创建线程池的管理类
    public static ThreadPoolManager getInstance(){
        return poolManager;
    }
    private ThreadPoolManager(){
        //创建线程池可以用ThreadPoolExecutor,也可以用Executors
        executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                //缓冲队列,超过核心线程的任务会被放到缓冲队列,
                // 这个构造方法可以传入一个int值表示缓冲队列的数目,实际中我们一般不加,表示可以缓冲Integer.MAX_VALUE这么多个
                //注意:任务和线程不一样,这里缓冲很多个不会造成内存溢出
                new LinkedBlockingDeque<Runnable>(),
                //这里一般这样写,使用默认的工厂
                Executors.defaultThreadFactory(),
                //当任务数超过线程池最大的数目时的策略,一般这样写
                new ThreadPoolExecutor.AbortPolicy());
    }
    
    /**
     * 添加任务的方法
     * @param runnable
     */
    public  void execut(Runnable runnable){
        if (runnable!=null){
            executor.execute(runnable);
        }
    }
    
    /**
     * 移除任务的方法
     * @param runnable
     */
    public void remove (Runnable runnable){
        if (runnable!=null){
            executor.remove(runnable);
        }
    }
    }
    

    4.执行过程
    (1)如果核心线程数还没到就放到核心线程去执行
    (2)如果核心线程已满,则放到任务队列等待
    (3)如果队列任务都满了,但还没有到达最大线程数,则开启一个非核心线程去执行任务
    (4)如果到达了最大线程数,则抛异常

    测试:

    public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("模拟器的核心数:"+Runtime.getRuntime().availableProcessors());
        for (int i = 0; i < 10; i++) {
            ThreadPoolManager.getInstance().execut(new ThreadDemo(i));
        }
    }
    class ThreadDemo implements Runnable{
        public int num;
        @Override
        public void run() {
            System.out.println(num+"-线程开始执行-----");
            SystemClock.sleep(3000);//模拟线程执行事件
            System.out.println(num+"-线程执行结束。。。");
        }
        public ThreadDemo(int num){
            this.num = num;
            System.out.println(num+"-线程等待执行");
        }
    }
    }
    

    结果输出:

    System.out: 模拟器的核心数:2
    System.out: 0-线程等待执行
    System.out: 1-线程等待执行
    System.out: 2-线程等待执行
    System.out: 3-线程等待执行
    System.out: 4-线程等待执行
    System.out: 5-线程等待执行
    System.out: 6-线程等待执行
    System.out: 7-线程等待执行
    System.out: 8-线程等待执行
    System.out: 9-线程等待执行
    System.out: 1-线程开始执行-----
    System.out: 3-线程开始执行-----
    System.out: 0-线程开始执行-----
    System.out: 4-线程开始执行-----
    System.out: 2-线程开始执行-----
    System.out: 1-线程执行结束。。。
    System.out: 5-线程开始执行-----
    System.out: 3-线程执行结束。。。
    System.out: 6-线程开始执行-----
    System.out: 0-线程执行结束。。。
    System.out: 7-线程开始执行-----
    System.out: 4-线程执行结束。。。
    System.out: 8-线程开始执行-----
    System.out: 2-线程执行结束。。。
    System.out: 9-线程开始执行-----
    System.out: 5-线程执行结束。。。
    System.out: 6-线程执行结束。。。
    System.out: 7-线程执行结束。。。
    System.out: 8-线程执行结束。。。
    System.out: 9-线程执行结束。。。
    

    相关文章

      网友评论

        本文标题:线程池的简单使用

        本文链接:https://www.haomeiwen.com/subject/uwukjxtx.html