当前位置: 首页 > news >正文

JavaEE-线程进阶


在这里插入图片描述在这里插入图片描述
在这里插入图片描述


模拟实现一个定时器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行结果如下:
在这里插入图片描述
上述模拟定时器的全部代码:

import java.util.PriorityQueue;//创建一个类,用来描述定时器中的一个任务
class MyTimerTask implements Comparable<MyTimerTask> {//任务执行时间private long time;//具体任务private Runnable runnable;//构造函数public MyTimerTask(Runnable runnable,long delay) {this.time = System.currentTimeMillis()+delay;this.runnable = runnable;}public long getTime() {return time;}public Runnable getRunnable() {return runnable;}@Overridepublic int compareTo(MyTimerTask o) {//时间小的任务,会被放置在队首return (int)(this.time-o.time);}
}//定时器类的本体
class MyTimer{//创建一个优先级队列存储上述的N个任务private PriorityQueue<MyTimerTask> queue=new PriorityQueue<>();//用来加锁的对象private Object locker=new Object();//提供一个schedule方法,把要执行的任务添加到队列中去public void  schedule(Runnable runnable,long delay){//new 一个任务对象synchronized (locker){MyTimerTask task=new MyTimerTask(runnable,delay);queue.offer(task);//每次来新的任务,都唤醒之前的扫描线程,让扫描线程根据当前的任务情况,重新规划等待时间locker.notify();}}//构造函数 提供一个扫描线程,一方面去监控队首元素是否到执行时间了,另一方面,如果到了执行时间,这需要调用这里的Runable中的run方法来完成任务public MyTimer(){Thread t=new Thread(() ->{while(true){try {synchronized (locker){while(queue.isEmpty()){//如果当前队列为空,就不应该去队列中取任务,使用wait进行等待,直到有任务加入队列locker.wait();}//判断当前队列中的队首元素距离执行时间的时间差MyTimerTask task=queue.peek();long curTime=System.currentTimeMillis();if(curTime>=task.getTime()){//当前时间大于等于任务的执行时间,开始执行queue.poll();//把已经执行的任务弹出队列task.getRunnable().run();//执行任务}else{//没有到任务时间,扫描线程休眠时间差//Thread.sleep(task.getTime()-curTime);locker.wait(task.getTime()-curTime);}}}catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}public class Demo21 {public static void main(String[] args) {MyTimer timer=new MyTimer();timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello 3");}},3000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello 2");}},2000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello 1");}},1000);System.out.println("程序开始运行");}
}

线程池
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


模拟实现一个线程池
只需要提交任务给线程池即可
核心操作为 submit, 将任务加入线程池中
使用一个 BlockingQueue 组织所有的任务

代码如下:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;//模拟实现一个线程池
class MyThreadPool{//将添加到线程池中的任务可以放置到这个队列中private BlockingQueue<Runnable> queue =new LinkedBlockingQueue<>();//通过这个方法可以将任务添加到线程池中public void  submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}//构造函数,创建一个线程池,数量为npublic  MyThreadPool(int n){for (int i = 0; i <n; i++) {Thread t=new Thread(() ->{while(true){try {//取放入线程池队列中的任务进行执行Runnable runnable= queue.take();runnable.run();} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}}
public class Demo23 {public static void main(String[] args) throws InterruptedException {MyThreadPool myThreadPool=new MyThreadPool(4);for (int i = 0; i <10; i++) {myThreadPool.submit(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"hello");}});}}
}

执行结果如下:

在这里插入图片描述

在这里插入图片描述


进阶内容


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
上述第二种情况的案例,如下
在这里插入图片描述
结果如下:
在这里插入图片描述
上述过程的所有代码:

//死锁
public class Demo24 {private  static  Object locker1=new Object();private  static  Object locker2=new Object();public static void main(String[] args) {Thread t1=new Thread(() ->{synchronized (locker1) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker2){System.out.println("t1 两把锁加锁成功");}}});Thread t2=new Thread(() ->{synchronized (locker2) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker1){System.out.println("t2 两把锁加锁成功");}}});t1.start();t2.start();}
}

我们可以通过jconsole来观察线程的执行过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
利用原子类实现线程安全
在这里插入图片描述
上述的代码如下:

import java.util.concurrent.atomic.AtomicInteger;//利用原子类实现线程安全
public class Demo25 {private static AtomicInteger count=new AtomicInteger(0);public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(() -> {for (int i = 0; i <5000; i++) {count.getAndIncrement();//后置++}});Thread t2=new Thread(() -> {for (int i = 0; i <5000; i++) {count.getAndIncrement();//后置++}});t1.start();t2.start();t1.join();t2.join();System.out.println(count.get());}
}

在这里插入图片描述

在这里插入图片描述


*加粗样式**


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述
下面利用Callable建立一个线程
在这里插入图片描述
上述过程的代码如下:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//利用Callable建立一个线程
public class Demo26 {public static void main(String[] args) throws ExecutionException, InterruptedException {Callable<Integer> callable =new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum=0;for (int i = 0; i <1000; i++) {sum+=i;}return sum;}};//callable不能直接用,需要借用FutureTask这个标签FutureTask<Integer> futureTask=new FutureTask<>(callable);Thread t =new Thread(futureTask);t.start();System.out.println(futureTask.get());}
}

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
下面简单使用一下这个信号量
在这里插入图片描述
上述过程的完整代码如下:

import java.util.concurrent.Semaphore;
//Semaphore  信号量
public class Demo27 {public static void main(String[] args) throws InterruptedException {//指定计数器的初始值Semaphore semaphore=new Semaphore(4);semaphore.acquire();System.out.println("执行了一次P操作");semaphore.acquire();System.out.println("执行了一次P操作");semaphore.acquire();System.out.println("执行了一次P操作");semaphore.acquire();System.out.println("执行了一次P操作");semaphore.acquire();System.out.println("执行了一次P操作");}
}

在这里插入图片描述同时等待 N 个任务执行结束.
在这里插入图片描述
上述过程的完整代码如下:

import java.util.concurrent.CountDownLatch;
//使用CountDownLatch将任务分配给多个线程来完成
public class Demo28 {public static void main(String[] args) throws InterruptedException {//指定创建任务的数量CountDownLatch countDownLatch=new CountDownLatch(10);for (int i = 0; i <10; i++) {int id=i;Thread t=new Thread(() ->{System.out.println( id + "开始工作");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println( id + "结束工作");// 每个任务执行结束这里, 调用一下方法,记录该线程是否结束// 把 10 个线程想象成短跑比赛的 10 个运动员. countDown 就是运动员撞线了.countDownLatch.countDown();});t.start();}// 主线程中可以使用 countDownLatch 负责等待任务结束.// a => all 等待所有任务结束. 当调用 countDown 次数 < 初始设置的次数, await 就会阻塞.countDownLatch.await();System.out.println("所有任务执行完毕");}
}

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述


相关文章:

JavaEE-线程进阶

模拟实现一个定时器 运行结果如下&#xff1a; 上述模拟定时器的全部代码&#xff1a; import java.util.PriorityQueue;//创建一个类&#xff0c;用来描述定时器中的一个任务 class MyTimerTask implements Comparable<MyTimerTask> {//任务执行时间private long …...

【开发篇】十五、Spring Task实现定时任务

文章目录 1、使用示例2、相关配置3、Scheduled注解4、Spring Task单线程下的阻塞坑5、Spring Task阻塞问题的处理思路6、Spring Task在分布式环境中 上一篇用Quartz来实现了定时任务&#xff0c;但相对来说&#xff0c;这个框架还是比较繁琐。Spring Boot默认在无任何第三方依赖…...

Python常用功能的标准代码

后台运行并保存log 1 2 3 4 5 6 7 8 9 nohup python -u test.py > test.log 2>&1 & #最后的&表示后台运行 #2 输出错误信息到提示符窗口 #1 表示输出信息到提示符窗口, 1前面的&注意添加, 否则还会创建一个名为1的文件 #最后会把日志文件输出到test.log文…...

Electron.js入门-构建第一个聊天应用程序

什么是electron 电子是一个开源框架&#xff0c;用于使用web技术构建跨平台桌面应用程序&#xff1b;即&#xff1a; HTML、CSS和JavaScript&#xff1b;被集成为节点模块&#xff0c;我们可以为我们的应用程序使用节点的所有功能&#xff1b;组件&#xff0c;如数据库、Api休…...

ubuntu 22.04 更新NVIDIA显卡驱动,重启后无网络图标等系统奇奇怪怪问题

环境 win10, ubuntu 22.04双系统 笔记本电脑&#xff0c;4060显卡 解决思路 具体的过程当时没有记录下来&#xff0c;然后因为在解决系统的问题&#xff0c;也没有截图啥的&#xff0c;只有一些大概记忆&#xff0c;供未来的自己参考吧。 首先是更新显卡驱动 我是直接在soft…...

Python综合案例:学生管理系统

目录 需求说明&#xff1a; 功能&#xff1a; 创建入口函数&#xff1a; 实现菜单函数&#xff1a; 实现增删查操作&#xff1a; 1. 新增学生 2. 展示学生 3. 查找学生 4. 删除学生 加入存档读档&#xff1a; 1. 约定存档格式 2. 实现存档函数 3. 实现读档函数 打…...

IDT 一款自动化挖掘未授权访问漏洞的信息收集工具

IDT v1.0 IDT 意为 Interface detection&#xff08;接口探测) 项目地址: https://github.com/cikeroot/IDT/该工具主要的功能是对批量url或者接口进行存活探测&#xff0c;支持浏览器自动打开指定的url&#xff0c;避免手动重复打开网址。只需输入存在批量的url文件即可。 …...

复习 --- 消息队列

进程间通信机制(IPC) 简述 IPC&#xff1a;Inter Process Communication 进程和进程之间的用户空间相互独立&#xff0c;但是4G内核空间共享&#xff0c;进程间的通信就是通过这4G的内核空间 分类 传统的进程间通信机制 无名管道&#xff08;pipe&#xff09; 有名管道&…...

AcWing 288. 休息时间,《算法竞赛进阶指南》

288. 休息时间 - AcWing题库 在某个星球上&#xff0c;一天由 N 个小时构成&#xff0c;我们称 0 点到 1 点为第 1 个小时、1 点到 2 点为第 2 个小时&#xff0c;以此类推。 在第 i 个小时睡觉能够恢复 Ui 点体力。 在这个星球上住着一头牛&#xff0c;它每天要休息 B 个小…...

ES6中字符串的扩展

字符串的遍历器接口 使用for…of for(let x of foo) {console.log(x); } // f; o; oat() ES5中的charAt()方法&#xff0c;返回字符串给定位置的字符。但是不能识别码点大于0xFFFF的字符&#xff0c;at方法可以 includes()、startsWith()、endsWith() 用来确定一个字符串是…...

GEO生信数据挖掘(四)数据清洗(离群值处理、低表达基因、归一化、log2处理)

检索到目标数据集后&#xff0c;开始数据挖掘&#xff0c;本文以阿尔兹海默症数据集GSE1297为例 目录 离群值处理 删除 低表达基因 函数归一化&#xff0c;矫正差异 数据标准化—log2处理 完整代码 上节围绕着探针ID和基因名称做了一些清洗工作&#xff0c;还做了重复值检查…...

CI/CD工具中的CI和CD的含义

CI/CD工具中的CI和CD的含义&#xff1f; CI/CD 是现代软件开发方法中广泛使用的一种方法。其中&#xff0c;CI 代表持续集成&#xff08;Continuous Integration&#xff09;&#xff0c;CD 则有两层含义&#xff0c;一是持续交付&#xff08;Continuous Delivery&#xff09;…...

用go获取IPv4地址,WLAN的IPv4地址,本机公网IP地址详解

文章目录 获取IPv4地址获取WLAN的IPv4地址获取本机公网IP地址 获取IPv4地址 下面的代码会打印出本机所有的IPv4地址。这个方法可能会返回多个IP地址&#xff0c;因为一台机器可能有多个网络接口&#xff0c;每个接口可能有一个或多个IP地址。 package mainimport ("fmt&…...

Android自定义Drawable---灵活多变的矩形背景

Android自定义Drawable—灵活多变的矩形背景 在安卓开发中&#xff0c;我们通常需要为不同的按钮设置不同的背景以实现不同的效果&#xff0c;有时还需要这些按钮根据实际情况进行变化。如果采用编写resource中xml文件的形式&#xff0c;就需要重复定义许多只有微小变动的资源…...

ParagonNTFSforMac_15.5.102中文版最受欢迎的NTFS硬盘格式读取工具

Paragon NTFS for Mac是一款可以为您轻松解决Mac平台上不能识别Windows通用的NTFS文件难题&#xff0c;这是一款强大的Mac读写工具&#xff0c;相信在很多时候&#xff0c;Mac用户需要对NTFS文件的移动硬盘进行写入&#xff0c;但是macOS系统默认是不让写入的&#xff0c;使用小…...

Kafka 搭建过程

目录 1.关于Kafka2.Kafka 搭建过程3.参考 本文主要介绍Kafka基本原理&#xff0c;以及搭建过程。 1.关于Kafka Apache Kafka是一个开源的分布式事件流平台&#xff0c;被设计用来实现实时数据流的发布、订阅、存储和处理。 Kafka的主要特性包括&#xff1a; 高吞吐量&#x…...

七、2023.10.1.Linux(一).7

文章目录 1、 Linux中查看进程运行状态的指令、查看内存使用情况的指令、tar解压文件的参数。2、文件权限怎么修改&#xff1f;3、说说常用的Linux命令&#xff1f;4、说说如何以root权限运行某个程序&#xff1f;5、 说说软链接和硬链接的区别&#xff1f;6、说说静态库和动态…...

一文教你搞懂Redis集群

一、Redis主从 1.1、搭建主从架构 单节点的Redis的并发能力是有上限的&#xff0c;要进一步的提高Redis的并发能力&#xff0c;据需要大家主从集群&#xff0c;实现读写分离。 共包含三个实例&#xff0c;由于资源有限&#xff0c;所以在一台虚拟机上&#xff0c;开启多个red…...

树上启发式合并 待补

对于每个子树&#xff0c;直接遍历所有轻儿子&#xff0c;继承重儿子 会了板子后&#xff0c;修改维护的东西和莫队是一样的 洛谷 U41492 #include <bits/stdc.h> #define ll long long #define ull unsigned long long constexpr int N1e55; std::vector<int> e…...

minio分布式文件存储

基本介绍 什么是 MinIO MinIO 是一款基于 Go 语言的高性能、可扩展、云原生支持、操作简单、开源的分布式对象存储产品。基于 Apache License v2.0 开源协议&#xff0c;虽然轻量&#xff0c;却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应…...

Linux新的IO模型io_uring

一、Linux下的网络通信模型 在网络开发的过程中&#xff0c;需要处理好几个问题。首先是通信的内核支持问题&#xff1b;其次是通信的模型问题&#xff1b;最后是框架问题。这些问题在闭源的OS如Windows上&#xff0c;基本上不算什么大问题&#xff08;因为只能用人家的API&am…...

FFmpeg 命令:从入门到精通 | FFmpeg 基本介绍

FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍FFmpeg 简介FFmpeg 基础知识复用与解复用编解码器码率和帧率 资料 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍 本系列文章要解决的问题&#xff1…...

数组篇 第一题:删除排序数组中的重复项

更多精彩内容请关注微信公众号&#xff1a;听潮庭。 第一题&#xff1a;删除排序数组中的重复项 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应…...

堆的初步认识

在学习本节文章前要先了解&#xff1a;大顶堆与小顶堆&#xff1a; &#xff08;优先级队列_加瓦不加班的博客-CSDN博客&#xff09; 堆实现 计算机科学中&#xff0c;堆是一种基于树的数据结构&#xff0c;通常用完全二叉树实现。 什么叫完全二叉树&#xff1f; 答&#x…...

CycleGAN模型之Pytorch实战

一、CycleGAN基本介绍 1. CycleGAN论文:《Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks》 2. 原文代码:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix 3. 网传精简代码:https://github.com/aitorzip/PyTorch-CycleGAN …...

C++(STL容器适配器)

前言&#xff1a; 适配器也称配接器&#xff08;adapters&#xff09;在STL组件的灵活组合运用功能上&#xff0c;扮演着轴承、转换器的角色。 《Design Patterns》对adapter的定义如下&#xff1a;将一个class的接口转换为另一个class的接口&#xff0c;使原本因接口不兼容而…...

软考 系统架构设计师系列知识点之软件架构风格(7)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之软件架构风格&#xff08;6&#xff09; 这个十一注定是一个不能放松、保持“紧”的十一。由于报名了全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;11月4号就要考试&#xff0c;因此…...

【Vue3】自定义指令

除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外&#xff0c;Vue 还允许你注册自定义的指令 (Custom Directives)。 1. 生命周期钩子函数 一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。 在 <script …...

UG\NX CAM二次开发 加工模块获取 UF _ask_application_module

文章作者:代工 来源网站:NX CAM二次开发专栏 简介: UG\NX CAM二次开发 加工模块获取 UF _ask_application_module 代码: void MyClass::do_it() { // TODO: add your code here // 获取NX当前所在的模块 int module_id = 0; // UF_ask_application_module(&…...

借助GPU算力编译Android

借助GPU算力编译Android 借助GPU编译Android代码的意义在于提高编译的效率和速度。传统的CPU编译方式在处理大量代码时可能会遇到性能瓶颈,而GPU编译利用了显卡的并行计算能力,可以同时处理多个任务,加快编译过程。通过利用GPU的并行计算能力,可以将编译过程中的多个任务分…...

佛山本科网站建设/手机网站关键词seo

增量备份与恢复的特点增量备份的优点是没有重复数据&#xff0c;备份量不大&#xff0c;时间短。但缺点也很明显&#xff0c;需要建立在上次完全备份及完全备份之后所有的增量才能恢复。MySQL没有提供直接的增量备份方法&#xff0c;但是可以通过mysql二进制日志间接实现增量备…...

大型网站开发协调/武汉seo创造者

电流流向&#xff1a; NPN PNP 它最主要的功能是电流 放大和开关作用。Emitter&#xff0c;Base&#xff0c;Collector NPN管&#xff0c;集电极电流IC和基极电流IB流入管子。发射极电流IE流出管子。且ICIBIE。 IcbIbe…...

网站县区分站点建设/怎么创建自己的网站平台

...

好的交互设计网站/免费手机优化大师下载安装

题目&#xff1a; 我是超链接 题解&#xff1a; 能够看出来这道题目是网络流&#xff0c;但并不清楚这个图怎么建 这种有交换次数限制的要考虑分成两半&#xff1a;最多流入的数量&#xff0c;最多流出的数量 作为流量限制 我们对于每个节点拆成三个点&#xff1a;x1&…...

微信公众号申请网站/搜索引擎推广渠道

在上篇我们介绍了tensorflow搭建全连接神经网络的基本原理&#xff0c;接下来开始用python实现在线推理、训练模型、在UI界面上实现预测识别。代码清单为&#xff1a; mnist_inference.py、mnist_train.py、NumReco.py、simpleUi.py 本节介绍mnist_inference.py。实现前向传播…...

新疆建设厅网官方网站/活动推广方式都有哪些

关注并星标TC互联&#xff0c;和广大技术传播者紧密互联&#xff01;搞定报错信息设计&#xff0c;轻松提升用户体验在数字产品的用户体验设计中&#xff0c;只有在最理想的情况中&#xff0c;才能做到让用户和应用程序百分之百地顺畅交互&#xff0c;并且不出现任何错误、技术…...