线程池实现

⭐ 作者:小胡_不糊涂
作者主页:小胡_不糊涂的个人主页
收录专栏:JavaEE
持续更文,关注博主少走弯路,谢谢大家支持

线程池

  • 1. 什么是线程池
  • 2. 标准库中的线程池
  • 3. 线程池模拟实现

1. 什么是线程池

想象这么⼀个场景:
在学校附近新开了⼀家快递店,⽼板很精明,想到⼀个与众不同的办法来经营。店⾥没有雇⼈,⽽是每次有业务来了,就现场找⼀名同学过来把快递送了,然后解雇同学。这个类⽐我们平时来⼀个任务,启动⼀个线程进⾏处理的模式。

很快⽼板发现问题来了,每次招聘 + 解雇同学的成本还是⾮常⾼的。⽼板还是很善于变通的,知道了为什么⼤家都要雇⼈了,所以指定了⼀个指标,公司业务⼈员会扩张到3个⼈,但还是随着业务逐步雇⼈。于是再有业务来了,⽼板就看,如果现在公司还没3个⼈,就雇⼀个⼈去送快递,否则只是把业务记下来,等着3个快递⼈员空闲的时候去处理。这个就是我们要带出的线程池的模式

线程池最⼤的好处就是减少每次启动、销毁线程的损耗。

2. 标准库中的线程池

在Java中可以使⽤Executors.newFixedThreadPool(10) 能创建出固定包含10个线程的线程池。返回值类型为 ExecutorService,然后通过 ExecutorService.submit 可以注册⼀个任务到线程池中。

public static void main(String[] args) {
        ExecutorService  service=Executors.newFixedThreadPool(10);
        service.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
    }

Executors 创建线程池的几种⽅式:

  • newFixedThreadPool:创建固定线程数的线程池
  • newCachedThreadPool:创建线程数⽬动态增⻓的线程池
  • newSingleThreadExecutor:创建只包含单个线程的线程池
  • newScheduledThreadPool:设定延迟时间后执⾏命令,或者定期执⾏命令。是进阶版的 Timer
    Executors 本质上是 ThreadPoolExecutor 类的封装

ThreadPoolExecutor 提供了更多的可选参数,可以进⼀步细化线程池⾏为的设定:
线程池实现_第1张图片

  • corePoolSize:正式员⼯的数量。(正式员⼯,⼀旦录⽤,永不辞退)
  • maximumPoolSize:正式员⼯ + 临时⼯的数⽬。(临时⼯:⼀段时间不⼲活,就被辞退)
  • keepAliveTime:临时⼯允许的空闲时间
  • unit:keepaliveTime 的时间单位
  • workQueue:传递任务的阻塞队列
  • threadFactory:创建线程的⼯⼚,参与具体的创建线程⼯作。通过不同线程⼯⼚创建出的线程相当于对⼀些属性进⾏了不同的初始化设置
  • RejectedExecutionHandler:拒绝策略,如果任务量超出公司的负荷了接下来怎么处理

3. 线程池模拟实现

主要思路:
1.提供构造方法,指定创建多少个线程
2.在构造方法中,把这些线程都创建好
3.有一个阻塞队列,能够持有要执行的任务
4.提供submit方法,可以添加新的任务

class MyThreadPoolExecutor{
    private List<Thread> threadList=new ArrayList<>();//保存产生的线程
    private BlockingQueue<Runnable> queue=new ArrayBlockingQueue<>(1000);//保存任务的队列

    //通过n指定创建多少个线程
    public  MyThreadPoolExecutor(int n) {
        for (int i = 0; i < n; i++) {
            //取出任务并执行
            Thread t = new Thread(() -> {
                while(true){
                    try {
                        Runnable runnable=queue.take();///如果队列为空,take就会阻塞
                        runnable.run();//取出一个执行一个
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            });
            t.start();
            threadList.add(t);
        }
    }
    //把任务传到队列中
    public void submit(Runnable runnable) throws InterruptedException {
            queue.put(runnable);
    }
}

测试类:

public class TestDemo9 {
    //public static volatile int i=0;
    public static void main(String[] args) throws InterruptedException {
        MyThreadPoolExecutor executor = new MyThreadPoolExecutor(4);
        for (int i = 0; i < 10; i++) {
            int n = i;//防止变量捕获(不可以是一直变化的值)-->volatile
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("执行任务" + n + "当前任务的线程为:" + Thread.currentThread().getName());
                }
            });

        }
    }
} 

线程池实现_第2张图片

多个线程之间的执行顺序是不确定的,某个线程取到任务也并非是立即就执行,就会产生无序的结果。但此处这些线程都是等价的。

你可能感兴趣的:(JavaEE,线程池)