【八股】线程池

1.线程池的核心参数在这里插入图片描述

corePoolSize - 核心线程数
maximumPoolSize - 最大线程数
keepAliveTime - 生存时间
unit - 时间单位
workQueue - 阻塞线程队列
threadFactory - 线程工厂
handler - 拒绝策略

源码里某些类和接口的一些关系:
ThreadPoolExecutor —继承—> AbstractExecutorService —实现—>ExecutorService(接口) —继承—> Executor(函数式接口)

Executors 类 (注意和上面的Executor接口不一样) 提供了使用了 ThreadPoolExecutor 的简单的 ExecutorService 实现,比如可以通过Executors.newFixedThreadPool()来创建线程池,底层还是调用new ThreadPoolExecutor来创建线程池

一个简单demo:

public class Main  {
    static public class WorkerThread implements Runnable {
        private String command;
        public WorkerThread(String s){
            this.command=s;
        }
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
            processCommand();
            System.out.println(Thread.currentThread().getName()+" End.");
        }
        private void processCommand() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        @Override
        public String toString(){
            return this.command;
        }
    }
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread("" + i);
            executor.execute(worker);
        }
        executor.shutdown(); // This will make the executor accept no new threads and finish all existing threads in the queue
        while (!executor.isTerminated()) { // Wait until all threads are finish,and also you can use "executor.awaitTermination();" to wait
        }
        System.out.println("Finished all threads");
    }
}

在这里插入图片描述

自定义拒绝策略,实现RejectedExecutionHandler接口,并监控线程池:

/**
 * 自定义线程实现Runnable
 */
class WorkerThread implements Runnable {

    private String command;

    public WorkerThread(String s){
        this.command=s;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
        processCommand();
        System.out.println(Thread.currentThread().getName()+" End.");
    }

    private void processCommand() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString(){
        return this.command;
    }
}
/**
 * 自定义拒绝策略
 */
class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println(r.toString() + " is rejected");
    }

}

/**
 * 监控线程池信息的线程
 */
class MyMonitorThread implements Runnable
{
    private ThreadPoolExecutor executor;

    private int seconds;

    private boolean run=true;

    public MyMonitorThread(ThreadPoolExecutor executor, int delay)
    {
        this.executor = executor;
        this.seconds=delay;
    }

    public void shutdown(){
        this.run=false;
    }

    @Override
    public void run()
    {
        while(run){
            System.out.println(
                    String.format("[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s",
                            this.executor.getPoolSize(),
                            this.executor.getCorePoolSize(),
                            this.executor.getActiveCount(),
                            this.executor.getCompletedTaskCount(),
                            this.executor.getTaskCount(),
                            this.executor.isShutdown(),
                            this.executor.isTerminated()));
            try {
                Thread.sleep(seconds*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
public class Main  {

    public static void main(String[] args) throws InterruptedException {
        //RejectedExecutionHandler implementation
        RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl();
        //Get the ThreadFactory implementation to use
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        //creating the ThreadPoolExecutor
        ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, rejectionHandler);
        //start the monitoring thread
        MyMonitorThread monitor = new MyMonitorThread(executorPool, 3);
        Thread monitorThread = new Thread(monitor);
        monitorThread.start();
        //submit work to the thread pool
        for(int i=0; i<10; i++){
            executorPool.execute(new WorkerThread("cmd"+i));
        }

        Thread.sleep(30000);
        //shut down the pool
        executorPool.shutdown();
        //shut down the monitor thread
        Thread.sleep(5000);
        monitor.shutdown();
    }
}

在这里插入图片描述

2. 线程池的执行原理

提交任务后,最多3步

  1. 核心线程是否全都被占用。如果没有全被占用,就分配一个核心线程执行任务
  2. 阻塞队列是否已满。如果没满,就放入阻塞队列
  3. 线程数是否小于最大线程数。如果是,就创建非核心线程去执行任务

如果上面都不行,就执行拒绝策略。默认的拒绝策略是直接抛出异常。

为什么不允许用Executors去创建线程池?推荐方式是什么?

比如说newFixedThreadPool:他的阻塞队列没有指定容量,可能会造成请求处理队列里有很多堆积,耗费很大的内存,甚至OOM 在这里插入图片描述

再比如说newCachedThreadPool():他new的ThreadPoolExecutor的最大线线程数是Integer.MAX_VALUE,有可能会创建非常多的线程,甚至OOM
在这里插入图片描述

推荐方式:
自定义Spring线程工厂bean,使用时直接注入bean对象调用execute方法即可。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值