【Java多线程】对线程池的理解并模拟实现线程池

本文详细介绍了Java中的线程池概念,包括线程池的作用、用户态与内核态的区别,重点讲解了ThreadPoolExecutor类的构造和配置参数,以及Executors工厂类的使用。此外,还模拟实现了固定线程数的线程池,探讨了何时选择ThreadPoolExecutor或Executors的使用场景。
摘要由CSDN通过智能技术生成

目录

1、池

 1.1、线程池

2、ThreadPoolExecutor 线程池类

3、Executors 工厂类

4、模拟实现线程池



1、池

“池”这个概念见到非常多,例如常量池、数据库连接池、线程池、进程池、内存池。

所谓“池”的概念就是:(提高效率)
1、提前把要用的对象准备好
2、用完的对象也不立即释放,留着以备下次使用。
从而大大降低了线程频繁地创建销毁造成的开销

 1.1、线程池

线程池也是如此,提前把要使用的线程,在线程池中准备好,等到需要用时就从池子里取

出,用完之后再归还给池子。

(其中取出和归还操作都是属于纯用户态代码,这就比内核操作更快,更可控) 

上面提到了用户态,什么是用户态呢?

        设想一个场景,你在银行柜台办理业务,该业务需要用到身份证复印件,此时有两种选择:一种是柜员拿着你的身份证帮你去复印,一种是你自己去复印。

        显然自己去复印这个操作更加可靠,并且可控一些。如果交给柜员去复印,天知道柜员拿了你的身份证后还去做了什么,因为柜员本身需要处理的事情不止有帮你复印身份证这一件事,可能在帮你复印身份证的路上去做了别的事情,你能做的就只有在柜台前等柜员回来,这种操作显然更加不可控。

你自己去操作就相当于用户态,而柜员帮你操作就相当于是内核态

而类比到计算机上简单来说就是:

如果一个任务,是在用户程序上完成的,就属于用户态,此时更加的可控。

如果一个任务,是通过系统申请创建线程,需要由内核来完成,就属于内核态,此时更加不可控。

2、ThreadPoolExecutor 线程池类

 Java 在标准库中提供了 ThreadPoolExecutor 线程池类

  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数
  • keepAliveTime:空闲时保持存活的时间(针对临时线程的)
  • unit:存活时间的时间单位(s,min,ms,hour....)
  • workQueue:阻塞队列,和定时器类似,线程池中也可以持有很多个任务
  • threadFactory:线程工厂(这个类中的方法封装了 new Thread 的操作,同时给 Thread 设置了一些属性)
  • handler拒绝策略,当线程池中的阻塞队列满时,继续往队列中添加任务,此时线程池会执行什么样的操作就称为拒绝策略

针对拒绝策略,又分为四种:

1、继续添加任务直接拒绝接收并报错。【直接报错,新旧任务都不干了】

2、新的任务,由添加任务的线程负责执行。【谁揽的活儿谁干】

3、丢弃最旧的任务,新的添加进来。

4、丢弃新来的任务。

3、Executors 工厂类

ThreadPoolExecutor 本身用起来比较复杂,因此标准库还把 ThreadPoolExecutor 封装了一层,提供了另一个版本。

即 Executors 工厂类,通过这个类来创建出不同的线程池对象。

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

  • newFixedThreadPool: 创建固定线程数的线程池
  • newCachedThreadPool: 创建线程数目动态增长的线程池.
  • newSingleThreadExecutor: 创建只包含单个线程的线程池.
  • newScheduledThreadPool: 设定 延迟时间后执行命令,或者定期执行命令. 是进阶版的 Timer.
public class ExecutorDemo {
    public static void main(String[] args) {
        //将线程数设置为 10
        ExecutorService service = Executors.newFixedThreadPool(10);
        //使用 submit 方法向线程池中提交任务
        service.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello Executors");
            }
        });
    }
}

既然 ThreadPoolExecutor 和 Executors 都可以创建线程池,那么到底该用哪个呢?

正常情况下直接使用 Executors 工厂类即可,当 Executors 工厂类提供的方法无法满足使用时,或者是想要高度定制化线程池时,才去使用 ThreadPoolExecutor。

4、模拟实现线程池

这里模拟写一个固定线程数目的线程池,即模拟使用 newFixedThreadPool 创建的线程池。

分析要点:

1、首先需要提供构造方法,方法中指定创建多少个线程

2、在构造方法中,把这些线程都创建好

3、用一个阻塞队列,将要执行的任务保存起来

4、提供 submit 方法,用于添加新的任务到阻塞队列中

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

    public MyThreadPoolExecutor(int n) {  //创建n个线程
        for (int i = 0; i < n; i++) {
            Thread t = new Thread(() -> {
                //这些线程需要做的就是不断从任务队列中取出任务并执行
                while (true) {
                    try {
                        // take 带有阻塞功能,为空时自动阻塞
                        Runnable runnable = queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            //启动线程
            t.start();
            //将线程存入集合中,以备后续使用
            threadList.add(t);
        }
    }

    //submit 添加新的任务到队列中
    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }
}

【博主推荐】 

【Java多线程】线程中几个常见的属性以及状态-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/136122127?spm=1001.2014.3001.5501【Java多线程】Thread类的基本用法-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/136121421?spm=1001.2014.3001.5501【Java多线程】对进程与线程的理解-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/136115808?spm=1001.2014.3001.5501

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

  • 36
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hacynn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值