Java线程池的知识学习总结

线程池的好处:

  1. 重用存在的线程,减少对象创建、消亡的开销,性能佳;
  2. 可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞;
  3. 提供定时执行、定期执行、单线程、并发数控制等功能。

ThreadPoolExecutor构造方法如下:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        ...
    }

构造方法的参数说明:

  • corePoolSize:

             核心线程数量。如果运行线程数小于corePoolSize,直接创建新线程来处理任务,即使线程池中有其他线程是空闲的。

  • maximumPoolSize:

            线程最大线程数。如果线程池数量大于等于corePoolSize且小于等于maximumPoolSize的时候,只有当workQueue满的时候才会创建新线程来处理任务。

  • keepAliveTime:

           线程没有任务执行时最多保持多久时间终止

  • unit:

           keepAliveTime的时间单位,如TimeUnit.SECONDS

  • workQueue:

           阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响

  • threadFactory:

           线程工厂,用来创建线程。

  • rejectHandler:

           当拒绝处理任务时的策略。JDK主要提供了四种饱和策略:

            A)直接抛出异常(默认策略) AbortPolicy 

            B)用调用者所在线程执行任务 CallerRunsPolicy

            C)丢弃队列中最靠前的任务来执行当前任务  DiscardOldestPolicy

            D)直接丢弃当前任务  DiscardPolicy

使用TreadPoolExecute实例的四个基本方法:

  • execute():提交任务,交给线程池执行;
  • submit():提交任务,能够返回执行结果 execute + Future;
  • shutdown():关闭线程池,等待任务都执行完;
  • shutdownNow():关闭线程池,不等待任务执行完,也会暂停正在执行的线程。

适用于监控TreadPoolExecute的方法:

  • getTaskCount():线程池已执行和未执行的任务总数;
  • getCompletedTaskCount():已完成的任务数量;
  • getPoolSize():线程池的当前线程数量;
  • getActiveCount():当前线程池中正在执行任务的线程数量。

Exexutor框架接口:

  • Executors.newCachedThreadPool

           创建一个可缓存的线程池,如果线程池的长度超过处理的需要,可以灵活回收空闲线程,若无可回收,则新建线程。

        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("task:{}",index);
                }
            });
        }

        executorService.shutdown();
  • Executors.newFixedThreadPool

           创建一个定长线程池,可以控制线程最大并发数,超出的线程会在队列中等待。

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 10; i++) {
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("task:{}",index);
                }
            });
        }

        executorService.shutdown();
  • Executors.newScheduledThreadPool

           创建一个定长线程池,支持定时、周期性的任务执行。

        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);

        // 延迟一秒之后,每隔三秒执行一次
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                log.info("scheduled run");
            }
        },1,3,TimeUnit.SECONDS);

        // 也可以使用timer的schedule方法来实现定时功能
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("timer run");
            }
        },new Date(),5*1000);
  • Executors.newSingleThreadExecutor

           创建一个单线程化的线程池,只会用唯一一个工作线程执行任务。

        ExecutorService executorService = Executors.newSingleThreadExecutor();

        for (int i = 0; i < 10; i++) {
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("task:{}",index);
                }
            });
        }

        executorService.shutdown();

 

线程池的合理配置:

  1. CPU密集型任务,就需要尽量压榨CPU,参考值可以设为NCPU+1;
  2. IO密集型任务,参考值可以设置为2*NCPU。

你可能感兴趣的:(多线程)