【Java ee初阶】多线程(7)

一、线程池

线程池的一些参数:

corePoolSize:核心线程数量

maximumPoolSize:核心线程数量+临时线程数量

上述是“java 的线程池策略”(其他语言,其他库的线程池可能不同)

keepAliveTime :临时线程的存活时间.临时线程允许摸鱼的最大时间

Timeunit:时间单位:秒/分钟/毫秒...

workQueue:线程池要完成的任务队列,每个任务都是通过Runnable来进行描述的

线程池在使用的时候,首先会创建一些线程,然后需要调用者给线程池放一些任务,这些线程就会从队列中取出任务,并且执行里面的代码。

(*工厂设计模式:正常创建一个对象是通过构造方法,new出来的。但是构造方法存在一定缺陷的,工厂模式就用来填补上这样的缺陷。不用构造方法来出池化对象,通过一组静态方法来初始化对象,静态方法就可以起不同的名字来做区分了。)

ThreadFactory:线程工厂 这个类就是Thread类的工厂类,由于在线程池中,是需要创建很多线程的,创建出来的线程需要进行哪些初始化操作?就可以通过threadFactory来进行设定。

实际上就是通过newThread方法,针对Thread对象进行初始化,再把这个Thread对象返回出来。比如想把线程池中的线程,按照一定的规则,设置name,或者想把线程池的线程全都设置成后台线程,或者都设置xxx为优先级。

例如,我想要将笛卡尔坐标系下的点转化为极坐标下的点表示,那么——

然而,多个版本的构造方法,需要“重载”,而重载要求方法名称相同但是参数列表不能相同,这里的参数列表相同,因此无法构成重载。那么此时的解决方法也就是:

这就是用来构造Point对象的类,也被称为“工厂类”

RejectedExecutionHandler:拒绝策略

线程池,有任务列表、阻塞队列,当任务队列满了的时候,如果再次添加新的任务,会发生什么呢?

正常来说,除非特殊说明,我们写的代码是不希望有这种突发性的阻塞的,因为这种阻塞稍不留神可能就对程序造成不可预估的影响。

因此直接让添加任务的线程阻塞,其实是不太好的,不太好就意味着要有其他的方法——因此标准库的线程池就引入了“拒绝策略”

正常情况下,是线程池里面的线程执行任务的,但是现在线程池里面的线程忙不过来了,就只能由调用者自己找个线程来执行任务

标准库中提供了一个对ThreadPoolExecutor进行了封装的简化版本Executors,本质上也是工厂类,提供了一些工厂方法,对上述的ThreadPoolExecutor进行不同的初始化。

这里的工厂方法,就是在创建不同风格的线程池。

package Thread;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class demo39 {public static void main(String[] args) {//固定线程数目的线程池,核心线程数和最大线程数都是4ExecutorService executorService = Executors.newFixedThreadPool(4);//核心线程数设置为0,最大线程数设为一个Int最大值这样的线程池ExecutorService executorService1 = Executors.newCachedThreadPool();//固定只有一个线程的线程池(这个东西确实用的不多,可以通过这种方式来代替创建线程的方式)ExecutorService executorService2 = Executors.newSingleThreadExecutor();//这个线程池,本质上是一个定时器,放到这个线程池中的任务,会在一定时间之后执行ExecutorService executorService3 = Executors.newScheduledThreadPool(4);}}

现在我们来让这个线程池来执行一些任务,为了更清晰地看出这个任务做了10次,我们来对i进行打印。然而这里不能直接这么些,会出现“变量捕获”的问题。

这里通过这种方法来进行解决。

有些公司更加想要完全体的ThreadPoolExecutor,可控性更强。

如果队列中没有其他的任务,take就会阻塞,一直阻塞到其他线程执行submit为止

package Thread;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;class MyFixedThreadPool{ // 固定线程池。private BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>(); // 阻塞队列,用于存放任务。public MyFixedThreadPool(int n){ // 构造方法,初始化线程池。for(int i = 0; i < n; i++){ // 创建n个线程。Thread t = new Thread(()->{ // 创建线程。try {while (true) {Runnable task = blockingQueue.take(); // 从阻塞队列中取出任务。task.run(); // 执行任务。}} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}    });t.start();    }       
}public void submit(Runnable task) throws Exception{ // 提交任务。// 1. 将任务放入阻塞队列。blockingQueue.put(task);}
}public class demo40 {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubMyFixedThreadPool myFixedThreadPool = new MyFixedThreadPool(100); // 创建线程池。for(int i = 0; i < 10; i++){ // 提交1000个任务。int finalI = i; // 闭包。myFixedThreadPool.submit(()->{ // 提交任务。System.out.println("任务" + finalI + "正在执行"); // 打印任务正在执行。});}}}

二、定时器

定时器在java编程中是一个非常终于熬的组件。

阻塞队列,太重要了,太常用了,在实际工作中,会把阻塞队列单独封装成一个/一组服务器

定时器也是类似,也会被单独封装成一个/一组服务器,类似于闹钟。

为什么需要定时器呢?——编程中有些任务,不需要立即执行,而是要等一会儿,等到到一定时间的时候再去执行。

Java标准库提供了Timer这样的类,可以通过他来实现简单的定时器。

一开始输出:程序启动,过了4s之后输出“定时器执行任务”

自行实现一个定时器

package Thread;import java.util.PriorityQueue;class MyTimerTask implements Comparable<MyTimerTask>{private Runnable task;private long delay;private long time ;public MyTimerTask(Runnable task, long delay){this.task = task;this.time = delay + System.currentTimeMillis();}public Runnable getTask(){return task;}public long getTime(){return time;}public int compareTo(MyTimerTask o){ // 比较两个任务的时间,谁的时间小谁排在前面。return (int)(this.time - o.time); // 比较两个任务的时间,谁的时间小谁排在前面。} // 比较两个任务的时间,谁的时间小谁排在前面。
}//自己实现定时器
//定时器能够同时管理多个任务
//有一定的数据结构来组织这多个任务
//ArrayList不太合适
//更好的选择是优先级队列class MyTimer{private PriorityQueue<MyTimerTask> queue = new PriorityQueue<MyTimerTask>();private static Object locker = new Object();public MyTimer(){//创建线程Thread t = new Thread(()->{ // 线程的任务是不断地从队列中取出任务,并执行。while (true) {try { // 捕获异常。synchronized(locker){ // 出队列。if(queue.isEmpty()){locker.wait();}MyTimerTask task = queue.peek(); // 取出队列中的第一个任务。long curTime = System.currentTimeMillis(); // 获取当前时间。if(curTime < task.getTime()){ // 如果当前时间小于任务的时间,说明任务还没有到执行时间。locker.wait(task.getTime() - curTime);}else{queue.poll(); // 取出队列中的第一个任务。task.getTask().run(); // 执行任务。}}} catch (InterruptedException e) { // 捕获异常。e.printStackTrace(); // 打印异常栈。}}});t.start(); // 启动线程。}public void schedule(Runnable task, long delay){ synchronized(locker){ // 入队列。queue.offer(new MyTimerTask(task, delay)); // 入队列。locker.notify(); // 唤醒线程。} // 入队列。}
}public class demo42 {public static void main(String[] args) {MyTimer timer = new MyTimer(); // 创建定时器。timer.schedule(new Runnable() {@Overridepublic void run() { // 任务的执行逻辑。System.out.println("定时任务 3000"); // 打印出 hello world。}}, 3000);timer.schedule(new Runnable() {@Overridepublic void run() { // 任务的执行逻辑。System.out.println("定时任务 2000"); // 打印出 hello world。}}, 2000);        timer.schedule(new Runnable() {@Overridepublic void run() { // 任务的执行逻辑。System.out.println("定时任务 1000"); // 打印出 hello world。}}, 1000);}}

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

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

相关文章

Linux 常用指令详解

Linux 操作系统中有大量强大的命令行工具&#xff0c;下面我将分类介绍一些最常用的指令及其用法。 ## 文件与目录操作 ### 1. ls - 列出目录内容 ls [选项] [目录名] 常用选项&#xff1a; - -l&#xff1a;长格式显示&#xff08;详细信息&#xff09; - -a&#xff1a;显…

uv安装及使用

windows安装参考&#xff1a; 什么是python uv&#xff0c;如何在windows上安装uv&#xff0c;基础的用法有哪些&#xff1f;_windows安装uv-CSDN博客 https://zhuanlan.zhihu.com/p/6776864377 使用方式 方式1&#xff1a; 创建uv虚拟环境->激活环境->安装依赖&…

C#实现Socket通信:基于TCP/IP协议的网络编程

TCP/IP网络模型 最上层的是应用层&#xff0c;也就是我们日常可以接触到的&#xff0c;它会给数据添加对应的头部&#xff0c;并传输给传输层&#xff0c;应用层是我们日常会接触到的&#xff0c;比如HTTP&#xff0c;FTP&#xff0c;Telnet&#xff0c;DNS&#xff0c;SMTP。…

哈希算法、搜索算法与二分查找算法在 C# 中的实现与应用

在计算机科学中&#xff0c;哈希算法、搜索算法和二分查找算法是三个非常基础且常用的概念。它们分别在数据存储、数据查找、以及高效检索等场景中起着至关重要的作用。在 C# 中&#xff0c;这些算法的实现和使用也十分简便。本文将详细讲解这三种算法的原理、应用以及 C# 中的…

AI日报 · 2025年5月05日|雅诗兰黛与微软合作成立 AI 创新实验室,加速美妆产品研发与营销

1、苹果与 Anthropic 深化合作&#xff0c;内部测试 AI 驱动的新版 Xcode 据多方报道&#xff0c;苹果公司正与人工智能初创公司 Anthropic 合作&#xff0c;开发集成 AI 功能的新一代 Xcode 开发平台。该平台旨在利用 Anthropic 强大的 Claude Sonnet 模型&#xff0c;为开发…

python celery框架结合django的使用

学习目标&#xff1a; 通过文章了解celery的运行机制以及如何结合django去使用 熟悉celery的运行原理属性celery在django项目当中的配置如何启动运行celery框架 学习内容&#xff1a; 熟悉celery的运行原理&#xff0c;简单来说 Celery 是一个“任务排队机后台处理器”。帮你…

滑动窗口leetcode 904

代码&#xff1a; class Solution { public:int totalFruit(vector<int>& fruits) {int n fruits.size();unordered_map<int,int> window_type_count;int left 0;int ans 0;for(int right 0; right <n;right){while(window_type_count.size() 2 &&…

用可视化学习逆置法

1.逆置法思路 目标&#xff1a;将这个彩色数组向右旋转3步 &#x1f534;1 → &#x1f7e0;2 → &#x1f7e1;3 → &#x1f7e2;4 → &#x1f535;5 → &#x1f7e3;6 → ⚪7我们希望得到 &#x1f535;5 → &#x1f7e3;6 → ⚪7 → &#x1f534;1 → &#x1f7e0;…

Cisco Packet Tracer 选项卡的使用

目录 设备Config选项卡的使用 Realtime and Simulation模式&#xff08;数据包跟踪与分析&#xff09; 设备Desktop选项卡的使用 设备Config选项卡的使用 Hostname NVRAM Startup Config----Load 加载 INTERFACE 点击on Save 如果&#xff0c;不把Running Config保存为Sta…

pyqt写一个单片机配置界面

已经实现以下功能 1.可以选择单片机架构 2.选择完单片机架构后第二个框可以选择常见单片机型号 3.选择完常见单片机型号后第三个框可以选择内部资源如adc等&#xff08;可以选择多个内部资源&#xff09;4.选择完内部资源如adc等&#xff08;可以选择多个内部资源&#xff09;后…

丢失的数字 --- 位运算

目录 一&#xff1a;题目 二&#xff1a;算法原理 三&#xff1a;代码实现 一&#xff1a;题目 题目链接&#xff1a; 268. 丢失的数字 - 力扣&#xff08;LeetCode&#xff09; 二&#xff1a;算法原理 三&#xff1a;代码实现 class Solution { public:int missingNumb…

千锋教育Ansible自动化运维实战教程从入门到精通

简介 介绍 Ansible 的基本概念、自动化运维优势、应用场景及课程目标。 欢迎开启 Ansible 学习之旅&#xff01; 你好&#xff01;作为一名学习者&#xff0c;你即将通过这个 Ansible 自动化运维实战 课程&#xff0c;从零开始掌握自动化运维的超能力&#xff01;这个“简介”…

深入理解 TensorFlow 的模型保存与加载机制(SavedModel vs H5)

深入理解 TensorFlow 的模型保存与加载机制&#xff08;SavedModel vs H5&#xff09; 在使用 TensorFlow 进行模型训练后&#xff0c;模型的保存与加载是部署、复用和迁移学习的重要环节。TensorFlow 提供了两种主要的保存格式&#xff1a;SavedModel 和 HDF5 (.h5)。本篇文章…

C++之特殊类设计及类型转换

目录 一、设计一个不能被拷贝的类 二、设计一个只能在堆上创建对象的类 三、设计一个只能在栈上创建对象的类 四、设计一个不能被继承的类 五、设计一个只能创建一个对象的类(单例模式) 六、C语言中的类型转换 七、C中的三类类型转换 八、C强制类型转换 8.1、为什么C需…

制作一款打飞机游戏36:调度编辑器

我们正在创建一个调度编辑器。嗯&#xff0c;这个名字听起来可能有点奇怪&#xff0c;对吧&#xff1f;但如果你了解射击游戏中的“调度”&#xff0c;那就是敌人出现的时间表。 你可能已经看到了&#xff0c;我们有一个可以滚动的关卡。现在&#xff0c;我想增加一些交互性&a…

wordperss AI插件:AI图文+视频+长尾关键词自动生成,已内置deepseek、kimi全模型,支持简单一键接入更多自定义API

【2.17最新版】Linkreate wordperss AI插件&#xff1a;AI图文视频长尾关键词自动生成&#xff0c;已内置deepseek、kimi全模型。 支持自定义接入其它API&#xff0c;包括但不限于腾讯云API和它的deepseek模型 后台只需要设置对应的API url 、模型 、API key,就可以让插件调用…

从零开始学Python:开启编程新世界的大门

在当今数字化时代&#xff0c;Python作为一门简洁、高效且功能强大的编程语言&#xff0c;受到了越来越多人的喜爱与追捧。无论是数据科学、人工智能、Web开发&#xff0c;还是自动化脚本编写&#xff0c;Python都展现出了卓越的能力。本文将带领大家踏上Python学习之旅&#x…

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】3.2 缺失值检测与处理(NULL值填充/删除策略)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 缺失值检测与处理全攻略&#xff1a;NULL值填充与删除策略实战3.2 缺失值检测与处理3.2.1 缺失值类型与业务影响3.2.1.1 缺失值的三种形态3.2.1.2 业务影响分级 3.2.2 缺失值…

Java求职面试:Spring Boot与微服务的幽默探讨

Java求职者面试&#xff1a;技术与幽默的碰撞 场景概述 在某互联网大厂的面试现场&#xff0c;面试官严肃认真&#xff0c;程序员则是一个搞笑的水货角色。面试者名叫张伟&#xff0c;年龄28岁&#xff0c;硕士学历&#xff0c;拥有5年的Java开发经验。以下是面试的详细过程。…

使用 NGINX 实现 HTTP Basic 认证ngx_http_auth_basic_module 模块

一、前言 在 Web 应用中&#xff0c;对部分资源进行访问控制是十分常见的需求。除了基于 IP 限制、JWT 验证、子请求校验等方式外&#xff0c;最经典也最简单的一种方式便是 HTTP Basic Authentication。NGINX 提供的 ngx_http_auth_basic_module 模块支持基于用户名和密码的基…