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

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

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);
    }
}


目录
相关文章
|
2月前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
177 2
|
2月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
189 2
|
2月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
213 1
|
3月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
163 0
|
3月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
262 16
|
4月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
531 1
|
安全 算法 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(下)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
212 6
|
存储 安全 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(中)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
238 5