Java学习day28:线程池Pool(知识点非常非常的详解)

news2024/9/24 23:31:17

声明:该专栏本人重新过一遍java知识点时候的笔记汇总,主要是每天的知识点+题解,算是让自己巩固复习,也希望能给初学的朋友们一点帮助,大佬们不喜勿喷(抱拳了老铁!)


往期回顾

Java学习day27:join方法、生产者消费者模式(知识点详解)-CSDN博客

Java学习day26:和线程相关的Object类的方法、等待线程和唤醒线程(知识点详解)-CSDN博客

Java学习day25:守护线程、死锁、线程生命周期(知识点详解)-CSDN博客

 Java学习day28:线程池Pool

一、线程池Pool

1.什么是线程池

线程池是一个容纳了多个线程的容器,其中的线程可以反复的使用。省去了频繁创建线程的对象的操作,无需反复创建线程而消耗更多的资源

2.工作原理

 3.7种具体实现方法

在Java语言中,并发编程都是通过创建线程池来实现的,而线程池的创建方式也有很多种,每种线程池的创建方式都对应了不同的使用场景,总体来说线程池的创建可以分为以下两类: 

①通过 ThreadPoolExecutor 手动创建线程池。
②通过 Executors 执行器自动创建线程池。

 而以上两类创建线程池的方式,又有 7 种具体实现方法,每种实现方法都有不同特点,而实际开发基本用最后一种,前六种一半不用的,所以前面的大家以了解为主,但是也要知道,重点在于最后一个。

我们今天,先讲前六种,最后一种太重要知识点也太多了,我们单独拿出来讲。

1.FixedThreadPool(中文翻译就是,固定的线程池)

创建一个固定大小的线程池,可控制并发线程数。使用FixedThreadPool创建2个固定大小的线程池,执行任务的方法有两种:submit 和 execute,具体实现代码:

示例1:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo3 {
    public static void main(String[] args) {
        fixedThreadPool();
    }
    public static void fixedThreadPool() {
        // 创建 2 个线程的线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(2);

        // 创建任务
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("任务被执行,线程:" + Thread.currentThread().getName());
            }
        };

        // 线程池执行任务(一次添加 4 个任务)
        
        threadPool.submit(runnable);  // 执行方式 1:submit
        threadPool.execute(runnable); // 执行方式 2:execute
        threadPool.execute(runnable);
        threadPool.execute(runnable);
    }
}

示例2:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo2 {
    public static void main(String[] args) {

        //1.创建线程池 创建了两个线程
        ExecutorService threadPool = Executors.newFixedThreadPool(2);

        //2.任务
       Runnable run1 =  new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("晚上吃饭。线程为:" + Thread.currentThread().getName());

                }
            }
        };
        Runnable run2 =  new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    System.out.println("晚上睡觉。线程为:" + Thread.currentThread().getName());

                }
            }
        };
        Runnable run3 =  new Runnable() {
            @Override
            public void run() {
                //run方法中写的是需求!!
                for (int i = 0; i < 20; i++) {
                    System.out.println("晚上敲代码不睡觉。线程为:" + Thread.currentThread().getName());

                }
            }
        };
        //3.执行上上面的三个任务
        threadPool.submit(run1);
        threadPool.execute(run2);
        threadPool.execute(run3);

    }
}

 注意点:

Ⅰ.都可以概括为三个步骤:

①创建固定数量的线程池
②使用Runnable匿名内部类创建任务
③调用submit 或 execute执行任务

Ⅱ.run方法里面写的是任务需求,业务实现。

Ⅲ.记住,执行任务的时候,线程依旧是抢占式运行的。

2.Executors.newCachedThreadPool

创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。

示例

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Demo3 {
    public static void main(String[] args) {
        cachedThreadPool();
    }
    public static void cachedThreadPool() {
        // 创建线程池
        ExecutorService threadPool = Executors.newCachedThreadPool();
        // 执行任务
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("任务被执行,线程:" + Thread.currentThread().getName());
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                    }
                }
            });
        }
    }
}

使用场景:

CachedThreadPool 是根据短时间的任务量来决定创建的线程数量的,所以它适合短时间内有突发大量任务的处理场景。 

3.Executors.newSingleThreadExecutor

创建单个线程数的线程池,它可以保证先进先出的执行顺序。其底层实现是队列

示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Demo3 {
    public static void main(String[] args) {
        singleThreadExecutor();
    }

    public static void singleThreadExecutor() {
        // 创建线程池
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        // 执行任务
        for (int i = 0; i < 10; i++) {
            final int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(index + ":任务被执行");
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                    }
                }
            });
        }
    }
}

单个线程的线程池有什么意义?单个线程的线程池相比于线程来说,它的优点有以下 2 个:

Ⅰ.可以复用线程:即使是单个线程池,也可以复用线程。 

Ⅱ.提供了任务管理功能:单个线程池也拥有任务队列,在任务队列可以存储多个任务,这是线程无法实现的,并且当任务队列满了之后,可以执行拒绝策略,这些都是线程不具备的。

4.Executors.newScheduledThreadPool:

创建一个可以执行延迟任务的线程池。

示例

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Demo3 {
    public static void main(String[] args) {
        scheduledThreadPool();
    }

    public static void scheduledThreadPool() {
        // 创建线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);
        // 添加定时执行任务(1s 后执行)
        System.out.println("添加任务,时间:" + new Date());
        threadPool.schedule(new Runnable() {
                                @Override
                                public void run() {
                                    System.out.println("任务被执行,时间:" + new Date());
                                    try {
                                        TimeUnit.SECONDS.sleep(1);
                                    } catch (InterruptedException e) {
                                    }
                                }
                            }
                , 3, TimeUnit.SECONDS);
    }

}

threadPool.schedule(1,2,3)里面的三个参数,1是需要执行的任务,2是延迟执行时间,3是延迟执行时间单位,这里是秒。

5.Executors.newSingleThreadScheduledExecutor

创建一个单线程的可以执行延迟任务的线程池。此线程池可以看作是 ScheduledThreadPool 的单线程池版本。 

示例

ublic static void SingleThreadScheduledExecutor() {
    // 创建线程池
    ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
    // 添加定时执行任务(2s 后执行)
    System.out.println("添加任务,时间:" + new Date());
    threadPool.schedule(() -> {
        System.out.println("任务被执行,时间:" + new Date());
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
    }, 2, TimeUnit.SECONDS);
}
6.Executors.newWorkStealingPool

创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】

示例

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Demo3 {
    public static void main(String[] args) {
        workStealingPool();
    }

    public static void workStealingPool() {
        // 创建线程池
        ExecutorService threadPool = Executors.newWorkStealingPool();
        // 执行任务
        for (int i = 0; i < 10; i++) {
            final int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(index + " 被执行,线程名:" + Thread.currentThread().getName());
                }
            });
        }
        // 确保任务执行完成
        while (!threadPool.isTerminated()) {
        }
    }
}

 从上述结果可以看出,任务的执行顺序是不确定的,因为它是抢占式执行的。

 7.ThreadPoolExecutor

手动创建线程池的方式,它创建时最多可以设置7个参数。(开发中用,面试要考)这一个非常非常重要,我们拿出来,单独用一篇文章讲。

4.总结

线程池的创建方式总共有以下 7 种:

1. Executors.newFixedThreadPool创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。
2. Executors.newCachedThreadPool创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。
3. Executors.newSingleThreadExecutor创建单个线程数的线程池,它可以保证先进先出的执行顺序。
4. Executors.newScheduledThreadPool创建一个可以执行延迟任务的线程池。
5. Executors.newSingleThreadScheduledExecutor创建一个单线程的可以执行延迟任务的线程池。
6. Executors.newWorkStealingPool创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】
7. ThreadPoolExecutor手动创建线程池的方式,它创建时最多可以设置 7 个参数。

而**线程池的创建推荐使用最后一种 ThreadPoolExecutor 的方式来创建,因为使用它可以明确线程池的运行规则,规避资源耗尽的风险**。


以上,就是今天的所有知识点了。线程池是Java中非常非常重要的核心部分,前六种具体创建线程池的方式,即使开发用的不多,大家也需要了解掌握,大家要自己多花点时间,静下心看代码,写代码,多理解,多运用,重点是多去运用。

加油吧,预祝大家变得更强!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1430287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv5算法进阶改进(15)— 引入密集连接卷积网络DenseNet

前言:Hello大家好,我是小哥谈。DenseNet(密集连接卷积网络)是一种深度学习神经网络架构,它在2017年由Gao Huang等人提出。DenseNet的核心思想是通过密集连接(dense connection)来促进信息的流动和共享。在传统的卷积神经网络中,每个层的输入只来自于前一层的输出。而在…

c语言---操作符(详解)

目录 一、操作符的分类二、算术操作符三、 移位操作符3.1<<左移操作符3.1.1移位规则3.1.2直接上代码以及解释 3.2>> 右移操作符3.2.1移位规则3.2.2画图解释 3.3注意 四、位操作符&#xff1a;&、|、^、~4.1&按位与4.1.1按位与的计算逻辑4.1.2代码4.1.3运行…

Modbus协议学习第七篇之libmodbus库API介绍(modbus_write_bits等)

写在前面 在第六篇中我们介绍了基于libmodbus库的演示代码&#xff0c;那本篇博客就详细介绍一下第六篇的代码中使用的基于该库的API函数。另各位读者&#xff0c;Modbus相关知识受众较少&#xff0c;如果觉得我的专栏文章有帮助&#xff0c;请一定点个赞&#xff0c;在此跪谢&…

redis布隆过滤器(Bloom)详细使用教程

文章目录 布隆过滤器1. 原理2. 结构和操作3. 特点和应用场景4. 缺点和注意事项 应用-redis插件布隆过滤器使用详细过程安装以及配置springboot项目使用redis布隆过滤器下面是布隆过滤器的一些基础命令 扩展 布隆过滤器 Bloom 过滤器是一种概率型数据结构&#xff0c;用于快速判…

算法学习——华为机考题库5(HJ31 - HJ35)

算法学习——华为机考题库5&#xff08;HJ31 - HJ35&#xff09; HJ31 单词倒排 描述 对字符串中的所有单词进行倒排。 说明&#xff1a; 1、构成单词的字符只有26个大写或小写英文字母&#xff1b; 2、非构成单词的字符均视为单词间隔符&#xff1b; 3、要求倒排后的单…

Jmeter,如何从数组参数中取值

有个post请求&#xff0c;参数“equipment_ids”&#xff0c;是个数组&#xff0c;需求每次执行的时候&#xff0c;按顺序取equipment_ids中不同的值 要实现在 JMeter 中每次执行请求时按顺序取不同的 equipment_ids 中的值&#xff0c;你可以使用 Counter 元件来生成索引&…

Linux 磁盘空间占用率100%的排查

&#x1f4d1;前言 使用 Linux 操作系统时&#xff0c;可能会遇到磁盘空间不足的错误&#xff0c;这种错误通常会导致系统运行缓慢或崩溃。本文将介绍磁盘排查的方法。⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1…

【深入浅出Java性能调优】「底层技术原理体系」详细分析探索Java服务器性能监控Metrics框架的实现原理分析(Dropwizard度量基础案例指南)

深入探索Java服务器性能监控Metrics框架的实现原理分析 前提介绍Dropwizard MetricsDropwizard的特点Dropwizard的开发案例需要引入Maven依赖常用度量类型Meter(每秒请求数为单位测量请求率)定义度量核心MetricRegistry构建对应的Meter指标对象请求标记采样业务方法控制报告器…

【C++入门到精通】C++的IO流(输入输出流) [ C++入门 ]

阅读导航 引言一、C语言的输入与输出二、流是什么三、CIO流1. C标准IO流&#xff08;1&#xff09;istream&#xff08;2&#xff09;ostream&#xff08;3&#xff09;iostream&#xff08;4&#xff09;cin 和 cout 2. C文件IO流&#xff08;1&#xff09;ifstream&#xff0…

WPF简介

WPF早期名称为Avalon&#xff0c;是微软的一个项目&#xff0c;目的是构建统一的平面展示平台 WPF是一个与分辨率无关的UI框架&#xff0c;是一种基于矢量的呈现引擎技术&#xff1b;所用的语言为XAML(全称Extensible Application MarkupLanguage)&#xff0c;它的基本度量单位…

02 使用jdk运行第一个java程序:HelloWorld

使用jdk运行第一个java程序 1 HelloWorld小案例1.1 编写流程1.2 错误示例 首先在CMD命令行里面&#xff0c;使用javac xxxx.java&#xff0c; 进行编译&#xff0c;其中会有报错&#xff1b; 然后生成xxxx.class 文件&#xff0c;然后使用java xxxx.class 进行运行。 1 HelloWo…

回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&#xff09; 目录 回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&…

五大浏览器内核及代表浏览器,一文讲透!

Hi,我是贝格前端工场&#xff0c;在进行web前端开发的时候&#xff0c;浏览器兼容性一直是让所有前端工程师头疼的问题&#xff0c;其根源在于不同的浏览器应用了不同的内核&#xff0c;其对html、css、js的解析规则也是不一样的&#xff0c;作为前端开发的你&#xff0c;如果不…

2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模

上一篇已经对赛题进行详细分析了&#xff0c;而且大方向和基本的模型已经确定完毕&#xff0c;数据集都已经找到了&#xff0c;现在最重要的就是要分析风暴数据集以及建立时序预测模型&#xff0c;使用气候模型预测的数据&#xff0c;评估气候变化对未来极端天气事件频率和强度…

全面认识DOS系统

目录 一、DOS系统的功能 1.执行命令和程序&#xff08;处理器管理&#xff09; 2.内存管理 3.设备管理 4.文件管理 5.作业管理 二、文件与目录 三、文件类型与属性 1.系统属性&#xff08;S&#xff09; 2.隐含属性&#xff08;H&#xff09; 3.只读属性&#xff08…

深度学习手写字符识别:训练模型

说明 本篇博客主要是跟着B站中国计量大学杨老师的视频实战深度学习手写字符识别。 第一个深度学习实例手写字符识别 深度学习环境配置 可以参考下篇博客&#xff0c;网上也有很多教程&#xff0c;很容易搭建好深度学习的环境。 Windows11搭建GPU版本PyTorch环境详细过程 数…

华为机考入门python3--(6)牛客6-质数因子

分类&#xff1a;质数、素数 知识点&#xff1a; 取余符号% 5%3 2 取整符号// 5//3 1 list中int元素转str map(str, list) 题目来自【牛客】 def prime_factors(n): """ 输入一个正整数n&#xff0c;输出它的所有质因子&#xff08;重复的也…

python pygame实现倒计时

实现思路 获取开始时间、当前时间&#xff0c;通过当前时间-开始时间时间差&#xff0c;再通过倒计时的总时长-时间差即可实现&#xff01; 随着时间的流逝&#xff0c;当前时间会变大&#xff0c;也就导致时间差会变大&#xff0c;当使用总时长-时间差的时候&#xff0c;得到…

基于控制台的购书系统(Java 语言实现)

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》|《数据结构与算法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢…

【Nginx】nginx入门

文章目录 一、Web服务器二、Nginx三、Nginx的作用Web服务器正向代理反向代理 四、CentOS上安装Nginx(以CentOS 7.9为例) 一、Web服务器 Web 服务器&#xff0c;一般是指“网站服务器”&#xff0c;是指驻留于互联网上某种类型计算机的程序。Web 服务器可以向 Web 浏览器等客户…