美文网首页
线程池浅析

线程池浅析

作者: 若尘0328 | 来源:发表于2017-12-12 10:55 被阅读14次
//java中线程池构造方法
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 

corePoolSize
线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;
如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;
如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。
maximumPoolSize
线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize。
keepAliveTime
线程空闲时的存活时间,即当线程没有任务执行时,继续存活的时间。默认情况下,该参数只在线程数大于corePoolSize时才有用
TimeUnit
keepAliveTime的时间单位,和keepAliveTime搭配使用。
workQueue
workQueue必须是BlockingQueue阻塞队列。当线程池中的线程数超过它的corePoolSize的时候,线程会进入阻塞队列进行阻塞等待。通过workQueue,线程池实现了阻塞功能
threadFactory
创建线程的工厂,通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名
Executors静态工厂里默认的threadFactory,线程的命名规则是“pool-数字-thread-数字”
RejectedExecutionHandler(饱和策略)
线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:
(1)AbortPolicy:直接抛出异常,默认策略;
(2)CallerRunsPolicy:用调用者所在的线程来执行任务;
(3)DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
(4)DiscardPolicy:直接丢弃任务;
当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。
下面的代码演示自定义的饱和策略:

public class ThreadPoolDemo {
    private static CountDownLatch countDownLatch=new CountDownLatch(10);
    private static class Mywork implements Runnable{
        @Override
        public void run() {
            try {
                countDownLatch.await();
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        BlockingQueue<Runnable> quene=new LinkedBlockingQueue<>(5);
        RejectedExecutionHandler myReject=new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println(r+" is rejected");
            }
        };
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2,4,1, TimeUnit.SECONDS,quene,myReject);
        //此处开启十个任务,但是最大线程池数(4)+阻塞队列大小(5)=9,所以肯定会有一个饱和任务
        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.execute(new Mywork());
            countDownLatch.countDown();
        }
        threadPoolExecutor.shutdown();
    }
}

程序输出结果:

com.thread.threadpool.ThreadPoolDemo$Mywork@3941a79c is rejected 

下面通过一张图解释线程池中任务的执行过程:

任务执行过程
提交任务给线程池threadPoolExecutor.execute(new Mywork());首先会判断当前线程数量是否小于核心线程数,是就创建线程执行任务,如果等于核心线程数量话再去判断阻塞队列是否已经满了,如果没有满就把任务加入到阻塞队列中,如果满了再去判断当前线程数量是否小于线程池的最大线程数量,是的话就再创建线程执行任务,如果这时当前当前线程数量等于最大线程数量的话就会执行饱和策略。上面代码我们自定义了自己的饱和策略,只是打印了一下执行饱和策略的线程的类。
整个执行流程可以参考下面的任务提交的逻辑:
任务提交逻辑
结合上面的图再来看源码:
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

那么任务被加入到线程池是如何被执行的呢?且听下次分解!

相关文章

  • 线程池浅析

    corePoolSize线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于c...

  • 浅析-Java线程池

    简介 什么是线程池?顾名思义,线程池就是装线程的“池子”。如果把一个线程看做是一桶水,那么线程池就是用来装这一桶一...

  • Android线程池浅析

    引言 在Android开发中,只要是耗时的操作都需要开启一个线程来执行。例如网络访问必须放到子线程中执行,否则会抛...

  • 浅析Java线程池

    合理利用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提...

  • Android的AsyncTask异步任务浅析

    Android的AsyncTask异步任务浅析 实现原理 内部封装了2个线程池+1个Handler(Interna...

  • Java线程池原理浅析

    一、线程池工厂Executors 我们平时在使用线程池的时候一般都是通过Executors的newXxxxxPoo...

  • 浅析Java线程池 ExecutorService

    ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中....

  • Java 线程池源码浅析

    本文旨在弄清楚 线程和任务 在java线程池里的处理逻辑 更详细的源码解析参考: https://javadoop...

  • JDK线程池源码浅析

    出于功利的原因,很早之前就想搞清楚JDK线程池的原理,在工作不到一年的时候就点进源码去看了看,当然没看不懂。后来搜...

  • 【高并发】深度解析线程池中那些重要的顶层接口和抽象类

    大家好,我是冰河~~ 在上一篇《【高并发】不得不说的线程池与ThreadPoolExecutor类浅析[https...

网友评论

      本文标题:线程池浅析

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