推广 热搜: csgo  vue  2023  angelababy  gps  信用卡  新车  htc  落地  控制 

池本:池本和岸本的关系

   2023-04-26 网络整理佚名1990
核心提示:为解决以上弊端,我们引入线程池,线程池实际上就是一个存储线程的一个容器注:线程池的线程创建线程是有上限的,而这个上限可以自己设置运行结果中只有线程1、2、3,上面测试类中创建了四个任务,由此可见,创建了有限个线程池分析上面案例可知,利用Executors工具类创建线程池虽然方便,但不够灵活。利用Executors类创建

线程池 1.缺点

缺点一:使用时创建线程

class MyThreadextends Thread(
    @Override
    public void run() {
        // 多线程执行的一些代码
}

缺点2:线程用完后消失

MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();

以前我们需要线程的时候,就去创建对象,对象用完了,线程就消失了,这样会浪费操作系统的资源。

为了解决上面的缺点,我们引入了线程池,它其实就是一个存放线程的容器

2.导入

一开始,线程池是空的。 当我们把任务提交给线程池时,线程池本身会自动创建一个线程,任务会带着线程去完成任务

特例:当任务1还没有执行完,而任务2已经提交到线程池,此时线程池会继续创建新的线程对象,让任务2可以使用新的线程执行任务

在这里插入图片描述

注意:线程池中线程创建线程是有上限的,这个上限可以自己设置

3. 核心原理是创建池。 当池为空并提交任务时,池将创建一个新的线程对象。 任务执行完毕后,线程会归还池中。 下次再次提交任务时池本,无需新建线程,直接复用即可。 现有线程还好,但是如果提交任务时池中没有空闲线程,无法创建新线程,任务就会排队等待 4.创建线程池

注意:线程池一般不会关闭。 服务器每天 24 小时运行。 如果服务器没有关闭,随时可能有任务,线程池是不会关闭的。

Executors:线程池的工具类,通过调用方法返回不同类型的线程池对象

方法名称说明

公共静态 ExecutorService newCachedThreadPool()

创建无限线程池

public staticExecutorService newFixedThreadPool(int nThreads)

创建一个有上限的线程池

池本_池贤宇池贤秀_池本和岸本的关系

这里的“无上限”并不是真正意义上的没有上限。 它的最大值是int类型的最大值(21亿多),但是不用考虑线程不足的情况。 线程池还没有创建那么多 电脑死机了

4.1 创建无限线程池

测试类:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class test1 {
    public static void main(String[] args) {
        // 获取线程池对象
        ExecutorService pool = Executors.newCachedThreadPool();
        // 提交任务(多个任务)
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        // 销毁线程池
        pool.shutdown();
    }
}

我的可运行类:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}

运行结果:

在这里插入图片描述

可以看出线程池创建了四个线程对象来执行任务

4.2线程多路复用demo:

测试类:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class test1 {
    public static void main(String[] args) throws InterruptedException {
        // 获取线程池对象
        ExecutorService pool = Executors.newCachedThreadPool();
        // 提交任务(多个任务)
        pool.submit(new MyRunnable());
        // 让上一个任务完成任务将线程还给线程池
        // 结果就是一直使用线程一去执行任务
        Thread.sleep(1000);
        pool.submit(new MyRunnable());
        Thread.sleep(1000);
        pool.submit(new MyRunnable());
        Thread.sleep(1000);
        pool.submit(new MyRunnable());
        // 销毁线程池
        pool.shutdown();
    }
}

我的可运行类:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--->");
        //}
    }
}

运行结果:

在这里插入图片描述

由于线程在执行下一个任务前会休眠几秒,之前的任务已经执行完毕,后续的任务会一直使用第一个线程

4.3 创建capped线程池

池贤宇池贤秀_池本和岸本的关系_池本

测试类:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class test1 {
    public static void main(String[] args) {
        // 获取线程池对象
        ExecutorService pool = Executors.newFixedThreadPool(3);
        // 提交任务(多个任务)
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        // 销毁线程池
        pool.shutdown();
    }
}

我的可运行类:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}

运行结果:

在这里插入图片描述

运行结果中只有线程1、2、3,上面的测试类中创建了4个任务。 可以看到创建了有限数量的线程池

5.自定义线程池

通过上面的案例分析可以看出,使用Executors工具类创建线程池虽然方便,但是不够灵活。当提交的任务很多时,任务的执行需要排队,长度无法定义团队。 这时候我们可以自己创建一个线程池对象来修改我们要修改的参数。

使用Executors类创建线程池对象的方法源码如下,共七个参数

在这里插入图片描述

借助API帮助文档,查看ThreadPoolExecutor构造方法的参数说明

在这里插入图片描述

参数说明类型

核心池大小

核心线程数(不能小于0)

整数

最大池大小

池本和岸本的关系_池贤宇池贤秀_池本

线程池最大线程数(最大数>=核心线程数)

整数

保活时间

空闲时间(值)(不能小于0)

长的

单元

空闲时间(单位)(用 TimeUnitt 指定)

时间单位

工作队列

阻塞队列(不能为空)

阻塞队列

线程工厂

创建线程的方式(不能为null)

线程工厂

处理程序

执行任务过多时的解决方法(不能为null)

拒绝执行处理程序

5.1 案例一

池本和岸本的关系_池本_池贤宇池贤秀

提交任务量=核心线程数

有一个现有的线程池,并且存在以下规定,

结果:线程池创建三个线程分别处理这三个任务

在这里插入图片描述

5.2 案例二

提交任务量>核心线程数

有一个现有的线程池,并且存在以下规定,

结果:由于核心线程数为3,所以只能分配3个线程完成其中3个任务,剩下2个任务会放到阻塞队列中排队

在这里插入图片描述

5.3 案例三

提交任务量>核心线程数+阻塞队列长度

有一个现有的线程池,并且存在以下规定,

结果:一共提交了八个任务。 线程池先创建三个线程处理其中三个任务,然后将多出的三个线程放入阻塞队列中排队。 发现多了两个线程,线程池会重新创建。 两个临时线程处理剩下的两个任务

注意:任务的执行顺序不一定按照提交的先后顺序执行(先到服务队列)

临时线程创建条件:

5.3 情况四

提交任务量>核心线程数+阻塞队列长度+临时线程数

有一个现有的线程池,并且存在以下规定,

池贤宇池贤秀_池本和岸本的关系_池本

结果:移除分配的3个核心线程、3个临时线程和阻塞队列中的3个线程后,剩下的任务会触发任务拒绝策略池本,即abandon

在这里插入图片描述

任务拒绝策略说明

线程池执行器。 中止策略

默认策略:丢弃任务并抛出 RejectedExecutionException

线程池执行器。 丢弃策略

丢弃任务而不抛出异常。 不建议这样做

线程池执行器。 丢弃最旧策略

放弃队列中等待时间最长的任务,将当前任务加入队列

ThreadPoolExecutor.CallerRunsPolicv

调用任务的run()方法绕过线程池直接执行

任务解析策略是ThreadPoolExecutor中的一个内部类。 单独存在没有意义,需要依附于ThreadPoolExecutor,所以设置为内部类

池贤宇池贤秀_池本和岸本的关系_池本

创建静态内部类:new outer class。 内部类()

只要理解上面的任务拒绝策略

ThreadPoolExecutor.DiscardoldestPolicy 丢弃队列中的第一个任务。 在情况 4 中,任务 4 将被丢弃

// 自定义线程池
ThreadPoolExecutor pool = new ThreadPoolExecutor(
    3, // /核心线程数量,能小于0
    6, // 最大线程数,不能小于0,最大数量 >= 核心线程数量
    60, // 空闲线程最大存活时间
    TimeUnit.SECONDS, // 时间单位
    new ArrayBlockingQueue<>(3), // 任务队列
    Executors.defaultThreadFactory(), // 创建线程工厂
    new ThreadPoolExecutor.AbortPolicy() // 任务的拒绝策略
);

概括:

1.创建一个空池 2.提交任务时,线程池会创建一个线程来执行任务,执行完返回线程

不断提交任务,会有以下三个临界点

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON