JavaEE 08 线程池简介

简介: JavaEE 08 线程池简介

前言

前面我们谈完了定时器,单例模式,阻塞队列等的操作并且做了模拟实现,今天我们再来说一说线程池的操作以及一些锁策略.

注:本章几乎均为理论篇,实践较少.

下面就让我们开始吧.

线程池

我们知道因为进程的频繁创建和销毁,带来的开销过大,我们无法接受,所以我们引入了更轻量级的线程,但是其实这里的线程频繁消耗的话,带来的开销也是我们无法接受的,所以我们又想了两个方案,线程池方案或者是更加轻量级的协程/纤程

纤程本质上是靠程序员在用户态进行调度,不是靠内核的调度器来操作,这节省了很多的开销

举个例子,如果一个进程中开一千个线程,电脑就卡死了,但是开一千个协程,其实是轻轻松松的

线程池的应用来说就是把线程提前创建好,用完了不要着急销毁,放进线程池里,以备下次使用,在这个过程中并没有频繁的创建和销毁线程,所以相对来说开销就小得多了,只是从线程池中取线程来使用,用完了还给线程池即可

tips:内核态和用户态之间的交互可以理解为,你去银行办事情,工作人员让你去去整一个身份证复印件,你可以让他帮你整,或者去自己整,他帮你整的话你无法掌控他什么时候帮你整,但是你自己整的话就能确定自己的时间安排

JVM提供的线程池(了解参数即可)

这里我们只要了解最后一个线程池的参数即可,因为几个方法的参数是重复的,最后一个的参数是最全的.

corePoolSize: 核心线程数           一个线程池里,最少有多少个线程

maximumPoolSize :最大线程数    一个线程池中,最多有多少个线程

keepAliveTime:线程空闲超过这个时间阈值,就会被销毁

unit:                 时间单位,取分钟,秒,小时等等

workQueue:    和定时器一样,线程池也可以有很多任务,也可以设置为带有优先级的

threadFactory:  线程工厂,本质上是给new这个操作封装了一层,可能同名同参数的构造方法,这样构成不了重载,我们就想弥补一下这个缺陷,封装一层构造方法.

handler:拒绝策略(最重要的)

以下是四个Java标准库中提供的拒绝策略

解决的是在阻塞队列满了之后,你还想往里面添加任务,我们以何种方式拒绝

第一种:直接不干了,旧任务和新任务都不干了,直接抛一个异常

第二种:新的任务,由添加任务的线程自己执行

第三种:丢弃一个最老的任务来执行这个任务

第四种:直接丢弃最新的任务

.

但是这个类使用起来还是比较复杂的,所以标准库还提供了另一个版本来简化操作,Exectors

都是通过submit添加任务,只不过是构造方法有所差异

所以如果你想实现高度定制化的线程池就使用上面这个很多参数的,不然就可以使用Exectors即可

注:一个线程池中有多少线程不是根据网上说的cpu核心数-1等等这么简单,其实还是有很多细节之处的,需要我们通过测试来决定,因为有些线程是IO密集型,有些是cpu密集型的,根据情况而定

线程池的简单实现

使用一个列表来存放队列,使用一个阻塞队列来存放任务,其中只有一个submit方法来新建任务

class MyThreadPool{
    private List<Thread> threadList = new ArrayList<>();
    private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);
    public MyThreadPool(int n){
        for (int i = 0; i < n; i++) {
            Thread t = new Thread(()->{
                //TODO
                while(true){
                    try {
                        //队列为空则会阻塞
                        Runnable runnable = queue.take();
                        //取出任务直接执行就行
                        runnable.run();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            t.start();
            threadList.add(t);
        }
    }
    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }
}
相关文章
|
22小时前
|
Java
【JavaEE】——多线程常用类
Callable的call方法,FutureTask类,ReentrantLock可重入锁和对比,Semaphore信号量(PV操作)CountDownLatch锁存器,
|
22小时前
|
Java 关系型数据库 MySQL
【JavaEE“多线程进阶”】——各种“锁”大总结
乐/悲观锁,轻/重量级锁,自旋锁,挂起等待锁,普通互斥锁,读写锁,公不公平锁,可不可重入锁,synchronized加锁三阶段过程,锁消除,锁粗化
|
22小时前
|
Java Go 调度
【JavaEE】——线程池大总结
线程数量问题解决方式,代码实现线程池,ThreadPoolExecutor(核心构造方法),参数的解释(面试:拒绝策略),Executors,工厂模式,工厂类
|
22小时前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
22小时前
|
Java 调度
|
22小时前
|
Java 调度
【JavaEE】——线程的安全问题和解决方式
【JavaEE】——线程的安全问题和解决方式。为什么多线程运行会有安全问题,解决线程安全问题的思路,synchronized关键字的运用,加锁机制,“锁竞争”,几个变式
|
22小时前
|
Java API 调度
【JavaEE】——多线程(join阻塞,计算,引用,状态)
【JavaEE】——多线程,join,sleep引起的线程阻塞,多线程提升计算效率,如何获取线程的引用和状态
|
22小时前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
22小时前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
22小时前
|
安全 前端开发 Java
【JavaEE】——线程的诞生(超详细、易理解)
进程对内存的管理,进程间的通信,进程的缺点,线程的概念和特点,进程和线程在内存中的分配方式,进程和线程的结合,进程和线程之间的关系,线程的缺点,有无线程的对比,线程的总结

相关实验场景

更多