Java线程池

创建线程的方法

- 实现Runnable接口
- 实现Callable接口
- 继承Thread类

为什么要使用线程池

- 降低资源消耗,减少创建线程的开销
- 提高响应速度,新任务可以由空闲线程立刻执行
- 可管理性,线程池统一管理

创建线程池的方法

Executors类提供了几个静态方法用于创建线程池

- newSingleThreadExecutor(),核心池大小为1,LinkedBlockingQueue(最大)
- newFixedThreadPool(n),指定核心池大小为
- newCachedThreadPool(),
- newScheduledThreadPool(),定时任务,有多线程实现和单线程实现

不建议使用Executors提供的几种线程池而要使用ThreadPoolExecutor的构造方法指定参数

防止OOM,Executors提供的几种线程池的等待队列没有设置大小限制(最大),可能会造成OOM,所以一般使用ThreadPoolExecutor的构造方法创建线程池:

public class ThreadPoolExecutor extends AbstractExecutorService {
    .....
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
        BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
    ...
}

线程池的参数

- corePoolSize:核心池大小
- maximumPoolSize:最大线程数
- keepAliveTime:线程的空闲时间
- unit:空闲时间的单位(时分秒毫秒)
- workQueue:等待队列/阻塞队列,有多种类型
- threadFactory:线程工厂,用来创建线程
- handler:拒绝策略,多种类型

线程池的状态

running=0
shutdown=1
stop=2
terminated=3

调用ThreadPoolExecutor的shutdown方法后,处于shutdown状态;
调用shutdownNow方法后,处于stop状态
所有工作线程已经销毁并且缓存队列清空,处于terminated状态

任务提交发生了什么

通过ThreadPoolExecutor.execute()方法提交任务,
如果线程数小于核心线程数,则创建线程执行任务;
否则,如果线程数小于最大线程数,则尝试将任务放进等待队列;
如果等待队列已满,并且线程数小于最大线程数,则新建线程执行该任务;
如果已达最大线程数,则采取拒绝策略。

关于keepAliveTime,当核心池已满时,会对核心池线程的空闲时间进行判断并回收,直至线程数不大于核心线程数。
如果还设置了allowCoreThreadTimeOut,那么在线程数小于等于核心线程数的时候也会回收

等待队列的类型

- ArrayBlockingQueue,必须指定大小
- LinkedBlockingQueue,默认大小为最大
- SynchronousQueue,新建线程执行任务

拒绝策略

- ThreadPoolExecutor.AbortPolicy:丢弃任务,抛出RejectedExecutionException异常
- ThreadPoolExecutor.DiscardPolicy:丢弃任务,不抛出异常
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前端的任务
- ThreadPoolExecutor.CallerRunsPolicy:调用者处理该任务

线程池的关闭

- shutdown():不再接受新任务,等待已有任务完成
- shutdownNow():不再接受新任务,尝试中断正在执行的任务并清空等待队列(通过调用每个线程的interrupt方法)

合理配置线程池大小

- cpu密集型:cpu+1
- IO密集型:2*cpu

线程池使用示例

public class ThreadTest {

    public static void main(String[] args) {
        ThreadPoolExecutor executor=new ThreadPoolExecutor(
                1000,2000,1000, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1000));
        for(int i=0;i<999;i++){
            MyTask myTask = new MyTask(i);
            executor.execute(myTask);
            System.out.println("核心池线程数: "+executor.getCorePoolSize()
                    +"等待队列: "+executor.getQueue().size()
                    +"已完成任务数"+executor.getCompletedTaskCount());
        }
        executor.shutdown();
    }
   
}
class MyTask implements Runnable{
    private int taskNum;

    public MyTask(int taskNum) {
        this.taskNum = taskNum;
    }

    @Override
    public void run() {
        System.out.println("开始task "+taskNum);
        try {
            Thread.currentThread().sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束task "+taskNum);
    }

}

参考:https://www.cnblogs.com/exe19/p/5359885.html

posted @ 2019-02-10 15:13  darknessplus  阅读(171)  评论(0编辑  收藏  举报