Java并发线程池底层原理详解与源码分析

1.线程池与线程性能对比

在单线程情况下处理任务的速度和用线程池对比性能有很大提升,线程池内部可以线程复用,在线程处理完任务以后可以回到线程池,处理其他任务,这样大大减少了线程销毁和创建的时间。

java自带的几种线程池:

ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorService executorService1 = Executors.newFixedThreadPool(100);
ExecutorService executorService2 = Executors.newSingleThreadExecutor();
ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

上面的线程池看构造参数都是用ThreadPoolExecutor创建,只是使用的参数不同。

newCachedThreadPool使用的构造方法:对应参数(核心线程数,最大线程数,线程存活时间,线程存活时间单位,队列),newCachedThreadPool只有0个核心线程,临时线程数可以无限大,所以它的执行效率很高,SynchronousQueue是一个典型的生产者消费者模式,相当于一个外包公司。

new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                              60L, TimeUnit.SECONDS,
                              new SynchronousQueue<Runnable>())
newCachedThreadPool使用的构造方法:核心线程数和临时线程数都是自定义的,LinkedBlockingQueue队列是一个无界阻塞队列,相当于可以无限等待任务处理,但是效率很低。相当于一个国企。
new ThreadPoolExecutor(nThreads, nThreads,
                              0L, TimeUnit.MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>())
newSingleThreadExecutor使用的构造方法:核心线程数和临时线程数都是1,相当于1个人处理无数的任务,效率在很快能处理完任务的时候很快,但是在需要处理任务很慢的时候就会显得效率很低。相当于一个私企,什么都是一个人干。
new FinalizableDelegatedExecutorService
    (new ThreadPoolExecutor(1, 1,
                            0L, TimeUnit.MILLISECONDS,
                            new LinkedBlockingQueue<Runnable>()))

最有可能出现OOM的线程池:newCachedThreadPool,里面不是无界队列,达到内存的最大值后会报OOM情况

前面三种情况阿里规范都不推荐,但在不是能达到内存top值的业务中上面三种都可以用,阿里推荐自定义线程池ThreadPoolExecutor

 1.1 线程池对比实战

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadDemo {

    public static void main(String[] args) {

        //定义3个线程池
        ExecutorService executorService = Executors.newCachedThreadPool();//很快
        ExecutorService executorService1 = Executors.newFixedThreadPool(100);//不快不慢
        ExecutorService executorService2 = Executors.newSingleThreadExecutor();//最慢

        //定义100个任务给线程池处理对比处理性能
        long begin = System.currentTimeMillis();
        for(int i=0;i<100;i++){
            executorService2.submit(new Task());
        }
        executorService.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("处理时间:"+(end-begin)/1000+"秒");
    }
}

class Task implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"处理完任务");

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
    }
}

1.2 ThreadPoolExecutor实战

/**
 * 第31个任务会拒绝任务
 */
public class ThreadDemo {

    public static void main(String[] args) {

        //定义ThreadPoolExecutor
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30, 0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10));
        //定义100个任务给线程池处理对比处理性能
        long begin = System.currentTimeMillis();
        for(int i=0;i<100;i++){
            threadPoolExecutor.submit(new Task());
        }
        threadPoolExecutor.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("处理时间:"+(end-begin)/1000+"秒");
    }
}

class Task implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"处理完任务");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

1.3 面试题1:自定义线程池参数

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
   
   

corePoolSize:核心线程数

int maximumPoolSize:最大线程数

long keepAliveTime:临时线程存活时间

TimeUnit unit:临时线程存活单位

BlockingQueue<Runnable> workQueue:任务队列

ThreadFactory threadFactory:一般自定义工厂类

RejectedExecutionHandler handler:拒绝策略,定义的有4种,一般我们可以自定义拒绝策略

AbortPolicy:默认抛出RejectedExecutionException拒绝任务
DiscardPolicy:抛弃任务
DiscardOldestPolicy:通过队列结构抛出最老的任务
CallerRunsPolicy:由调用execute方法的线程执行任务

1.4 面试题线程池源码分析执行原理图(TODO) 

1.5 面试题submit()与execute方法区别(TODO)

submit与execute的区别:在线程中存在一个提交优先级和执行优先级的概念,提交优先级高于执行优先级。
1. execute方法在submit方法中。
2. submit方法会返回Future泛型函数,而execute不返回

 

 

1.6 面试题offer()与add()区别

add和offer都是任务队列添加任务的方法,区别add方法不抛出异常,而offer会抛出中断异常,这是他们唯一的区别。

 

 

1.7 newScheduledThreadPool(TODO)

1.7.1 newScheduledThreadPool实战(TODO)

1.7.2 源码分析(TODO)

1.8 自定义拒绝策略

自定义拒绝策略两种方法:

//自定义拒绝策略
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println("自定义拒绝策略,可以存入数据库");
    }
};

第二种:实现RejectedExecutionHandler接口重写rejectedExecution方法。

import java.util.concurrent.*;

/**
 * 第31个任务会拒绝任务
 */
public class ThreadDemo {

    public static void main(String[] args) {

        //自定义拒绝策略
        RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println("自定义拒绝策略,可以存入数据库");
            }
        };

        //定义ThreadPoolExecutor
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30, 0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10),rejectedExecutionHandler);
        //定义100个任务给线程池处理对比处理性能
        long begin = System.currentTimeMillis();
        for(int i=0;i<100;i++){
            threadPoolExecutor.submit(new Task());
        }
        threadPoolExecutor.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("处理时间:"+(end-begin)/1000+"秒");
    }
}

class Task implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"处理完任务");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

猜你喜欢

转载自blog.csdn.net/qq_21575929/article/details/124939077