Java基础(四)

前言:本博客主要涉及java编程中的线程、多线程、生成者消费者模型、死锁。

目录

线程多线程

线程同步

synchronized

Lock锁

线程通信

生产者消费者模型

线程池

使用线程池处理Runnable任务

使用线程池处理Callable任务

Excutors

悲观锁

乐观锁

并发VS并行

线程的生命周期


线程多线程

创建一个简单的线程

获取执行当前代码的线程名:Thread.currentThread().getName()

开启线程:对象名.start()

守护线程 优先级

//1.创建一个继承于Thread类的子类
class MyThread extends Thread {//2.重写Thread类的run()@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}}
}public class ThreadTest {public static void main(String[] args) {MyThread t1 = new MyThread();t1.start();}
}
package learn12;class MyRunnable implements Runnable {@Overridepublic void run() {for (int i = 1; i <= 5; i++) {System.out.println("子线程输出:" + i);}}
}public class MyThreadTest2 {public static void main(String[] args) {Runnable target = new MyRunnable();new Thread(target).start();for (int i = 1; i <= 5; i++) {System.out.println("主线程main输出:" + i);}}}

线程安全

例子:多个人同时去一个账户里取钱,被取出后,不能再取出钱。但多个线程执行时,在访问时,账户里有钱的,但实际上已经被其他用户取走,此时再取钱就会引发数据不安全的问题。

使用多线程时,每个线程都对数据进行修改,如何来保证数据的安全性?

package learn12;public class Account {private String cardId;private double money;public Account() {}public Account(String cardId, double money) {this.cardId = cardId;this.money = money;}public String getCardId() {return cardId;}public void setCardId(String cardId) {this.cardId = cardId;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}public void drawMoney(double money) {String name = Thread.currentThread().getName();if (this.money >= money) {System.out.println(name + "来取钱" + money + "成功!");this.money -= money;System.out.println(name + "来取钱,此时剩余:" + this.money);} else {System.out.println(name + "来取钱,但余额不足");}}
}
package learn12;public class DrawThread extends Thread {private Account acc;public DrawThread(Account acc, String name) {super(name);this.acc = acc;}@Overridepublic void run() {acc.drawMoney(100000);}
}
package learn12;public class ThreadTest {public static void main(String[] args) {Account acc = new Account("ICBC-100", 100000);new DrawThread(acc, "小明").start();new DrawThread(acc, "小红").start();new DrawThread(acc, "小李").start();}
}

线程同步

使用了加锁的机制

synchronized

用到了同步控制关键字synchronized

用其修饰成员方法,被修饰的方法,在同一时间,只能被一个线程执行

//同步方法
public synchronized void drawMoney(double money) {String name = Thread.currentThread().getName();
//同步代码块synchronized (this) {if (this.money >= money) {System.out.println(name + "来取钱" + money + "成功!");this.money -= money;System.out.println(name + "来取钱,此时剩余:" + this.money);} else {System.out.println(name + "来取钱,但余额不足");}}}

Lock锁

注意:解锁要放在finally里,以便程序出错时,可以解锁。

package learn12;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Account {private String cardId;private double money;//创建Lock锁对象private final Lock lk = new ReentrantLock();public Account() {}public Account(String cardId, double money) {this.cardId = cardId;this.money = money;}public String getCardId() {return cardId;}public void setCardId(String cardId) {this.cardId = cardId;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}public void drawMoney(double money) {String name = Thread.currentThread().getName();//加锁lk.lock();try {if (this.money >= money) {System.out.println(name + "来取钱" + money + "成功!");this.money -= money;System.out.println(name + "来取钱,此时剩余:" + this.money);} else {System.out.println(name + "来取钱,但余额不足");}} catch (Exception e) {e.printStackTrace();} finally {//解锁lk.unlock();}}
}

线程通信

生产者线程负责生产数据

消费者线程负责消费生产者产生的数据

生产者消费者模型

package learn12;import java.util.ArrayList;
import java.util.List;public class Desk {private List<String> list = new ArrayList<>();public synchronized void put() {try {String name = Thread.currentThread().getName();if (list.size() == 0) {list.add(name + "做的肉包子");System.out.println(name + "做了一个肉包子");Thread.sleep(2000);//唤醒别人 等待自己this.notifyAll();this.wait();} else {//唤醒别人 等待自己this.notifyAll();this.wait();}} catch (InterruptedException e) {e.printStackTrace();}}public synchronized void get() {try {String name = Thread.currentThread().getName();if (list.size() == 1) {System.out.println(name + "吃了:" + list.get(0));list.clear();Thread.sleep(1000);//唤醒别人 等待自己this.notifyAll();this.wait();} else {//唤醒别人 等待自己this.notifyAll();this.wait();}} catch (InterruptedException e) {e.printStackTrace();}}
}
package learn12;public class ThreadTest4 {public static void main(String[] args) {Desk desk = new Desk();//生产者线程new Thread(() -> {while (true) {desk.put();}}, "厨师1").start();new Thread(() -> {while (true) {desk.put();}}, "厨师2").start();new Thread(() -> {while (true) {desk.put();}}, "厨师3").start();//消费者线程new Thread(() -> {while (true) {desk.get();}}, "吃货1").start();new Thread(() -> {while (true) {desk.get();}}, "吃货2").start();}
}

线程池

线程池就是一个可以复用线程的技术。

使用线程池的必要性:

用户发起一个请求,后台就需要创建一个新线程。不使用线程池,会产生大量的线程,会损害系统的性能。

线程池可以固定线程和执行任务的数量,可以避免系统瘫痪和线程耗尽的风险。

创建线程池

临时线程什么时候创建?

新任务提交时,发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时会创建临时线程。

什么时候可以拒绝新任务?

核心线程和临时线程都在忙,任务队列都满了,新的任务过来时才会开始拒绝任务。

使用线程池处理Runnable任务

package learn12;public class MyRunnableLearn implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "==>输出666");try {Thread.sleep(Integer.MAX_VALUE);} catch (InterruptedException e) {e.printStackTrace();}}
}
package learn12;import java.util.concurrent.*;public class ThreadPoolTest {public static void main(String[] args) {//创建线程池对象
//        new ThreadPoolExecutor(
//                                int corePoolSize,
//                                int maximumPoolSize,
//                                long keepAliveTime,
//                                TimeUnit unit,
//                                BlockingQueue<Runnable> workQueue,
//                                ThreadFactory threadFactory,
//                                RejectedExecutionHandler handler
//        )ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());Runnable target = new MyRunnableLearn();pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target);//都满了 拒绝新任务pool.execute(target);
//        pool.shutdownNow();//pool.shutdown();}
}

使用线程池处理Callable任务

package learn12;import java.util.concurrent.Callable;public class MyCallable implements Callable<String> {private int n;public MyCallable(int n) {this.n = n;}@Overridepublic String call() throws Exception {int sum = 0;for (int i = 1; i <= n; i++) {sum += i;}return Thread.currentThread().getName() + "求出了1-" + n + "的和是:" + sum;}
}
package learn12;import java.util.concurrent.*;public class ThreadPoolTest2 {public static void main(String[] args) throws Exception {ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());//使用线程池处理Callbable任务Future<String> f1 = pool.submit(new MyCallable(100));Future<String> f2 = pool.submit(new MyCallable(200));Future<String> f3 = pool.submit(new MyCallable(300));//复用前面的线程Future<String> f4 = pool.submit(new MyCallable(400));System.out.println(f1.get());System.out.println(f2.get());System.out.println(f3.get());System.out.println(f4.get());}
}

 

Excutors

大型并发系统环境中使用Excutors如果不注意可能会出现系统风险。

核心线程数

计算密集型任务:核心线程数量 = CPU核数+1

IO密集型任务:核心线程数量 = CPU核数*2

package learn12;import java.util.concurrent.*;public class ThreadPoolTest2 {public static void main(String[] args) throws Exception {//通过Executors创建一个线程池对象ExecutorService pool = Executors.newFixedThreadPool(3);Executors.newSingleThreadExecutor();//使用线程池处理Callbable任务Future<String> f1 = pool.submit(new MyCallable(100));Future<String> f2 = pool.submit(new MyCallable(200));Future<String> f3 = pool.submit(new MyCallable(300));//复用前面的线程Future<String> f4 = pool.submit(new MyCallable(400));System.out.println(f1.get());System.out.println(f2.get());System.out.println(f3.get());System.out.println(f4.get());}
}

悲观锁

一开始就加锁,每次只能一个线程进入访问完毕后,再解锁,线程安全,性能较差。

package learn12;public class MyRunnable implements Runnable {public int count;@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(this);synchronized (this) {System.out.println("count ===>" + (++count));}}}
}

 

package learn12;public class Test {public static void main(String[] args) {Runnable target = new MyRunnable();for (int i = 1; i <= 100; i++) {new Thread(target).start();}}
}

乐观锁

一开始不上锁,等要出现线程安全问题时,等要出现线程安全问题时,线程安全,性能较好。

如何实现乐观锁

private AtomicInteger count = new AtomicInteger();
package learn12;import java.util.concurrent.atomic.AtomicInteger;public class MyRunnable implements Runnable {private AtomicInteger count = new AtomicInteger();@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(this);synchronized (this) {System.out.println("count ===>" + count.incrementAndGet());}}}
}

并发VS并行

python进阶学习也涉及到这里的知识点。

Python进阶(二)-CSDN博客

进程:正在运行的程序

线程:一个进程中可以运行多个线程

并发:线程是由CPU调度执行的,但CPU能同时处理的线程数量有限,为了保证全部线程都能执行,CPU会轮询为系统的每个线程服务,由于CPU切换的速度很快,好像是线程在同时执行,这就是并发。

并行:同一时间点,任务同时地运行,比如一台电脑,有8个CPU,每个CPU的每个核心都可以独立地执行一个任务,在同一时间点,可同时执行8个任务,这时任务是同时执行,并行地运行任务。

线程的生命周期

New:新建

Runnable:可运行

Timinated:被终止

Timed Waiting:计时等待

Waiting:无线等待

Blocked:阻塞

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

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

相关文章

React 全栈体系(十三)

第七章 redux 五、redux 异步编程 1. 理解 redux 默认是不能进行异步处理的,某些时候应用中需要在 redux 中执行异步任务(ajax, 定时器) 2. 使用异步中间件 npm install --save redux-thunk 3. 代码 - 异步 action 版 3.1 store /* src/redux/store.js */ /*** 该文件专…

【Spatial-Temporal Action Localization(七)】论文阅读2022年

文章目录 1. TubeR: Tubelet Transformer for Video Action Detection摘要和结论引言&#xff1a;针对痛点和贡献模型框架TubeR Encoder&#xff1a;TubeR Decoder&#xff1a;Task-Specific Heads&#xff1a; 2. Holistic Interaction Transformer Network for Action Detect…

前端项目练习(练习-001-纯原生)

先创建一个空文件夹&#xff0c;名字为web-001,然后用idea开发工具打开&#xff0c;如图&#xff1a; 可以看到&#xff0c;这是个彻底的空项目&#xff0c;创建 index.html index.js index.css三个文件&#xff0c;如图&#xff1a; 其中&#xff0c;html文件内容如下&am…

Qt Charts简介

文章目录 一.图标类型Charts分类1.折线图和样条曲线图2.面积图和散点图3.条形图4.饼图5.误差棒图6.烛台图7.极坐标图 二.坐标轴Axes类型分类三.图例四.图表的互动五.图表样式主题 一.图标类型Charts分类 图表是通过使用系列类的实例并将其添加到QChart或ChartView实例来创建的…

RT-Thread(学习)

RT-Thread是一款完全由国内团队开发维护的嵌入式实时操作系统&#xff08;RTOS&#xff09;&#xff0c;具有完全的自主知识产权。经过16个年头的沉淀&#xff0c;伴随着物联网的兴起&#xff0c;它正演变成一个功能强大、组件丰富的物联网操作系统。 RT-Thread概述 RT-Threa…

基于 SpringBoot+Vue的电影影城管理系统,附源码,数据库

文章目录 第一章 简介第二章 技术栈第三章 功能分析第四章 系统设计第5章 系统详细设计六 源码咨询 第一章 简介 本影城管理系统&#xff0c;是基于 Java SpringBoot 开发的。主要包括二大功能模块&#xff0c;即用户功能模块和管理员功能模块。 &#xff08;1&#xff09;管…

渗透测试信息收集方法和工具分享

文章目录 一、域名收集1.OneForAll2.子域名挖掘机3.subdomainsBurte4.ssl证书查询 二、获取真实ip1.17CE2.站长之家ping检测3.如何寻找真实IP4.纯真ip数据库工具5.c段&#xff0c;旁站查询 三、端口扫描1.端口扫描站长工具2.masscan(全端口扫描)nmap扫描3.scanport4.端口表5.利…

【力扣每日一题】2023.9.23 树上的操作

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 这是一道程序设计类的题目&#xff0c;题目比较长&#xff0c;我稍微概括一下。 构造函数中给我们一个数组&#xff0c;第i个元素表示第…

最新Python大数据之Excel进阶

文章目录 Excel图表类型了解有哪些图表类型 Excel图表使用图表的创建方式利用固定数据区域创建图表编辑数据系列添加数据标签格式化图表 Excel数据透视表数据透视表对原始数据的要求创建数据透视表数据透视表字段布局将数据透视图变成普通图表 Excel图表类型 为了揭示数据规律…

如何模拟自然界生态系统中的食物链

本人最近在研究一款针对青少年儿童的教育游戏&#xff0c;希望从培养孩子各方面的综合素质出发&#xff0c;引导孩子掌握多方面的软知识&#xff0c;软技能。其中有一个比较新颖的游戏玩法------打猎。该玩法创新点在于&#xff0c;引入了食物链的概念。过去一般的游戏里&#…

时间复杂度、空间复杂度

一、时间复杂度 1、概念 时间复杂度&#xff1a;计算的是当一个问题量级增加的时间&#xff0c;时间增长的趋势&#xff1b; O&#xff08;大O表示法&#xff09;&#xff1a;渐进的时间复杂度 2、举例 ① 以下 for 循环的时间复杂度&#xff1a;O(1 3n) O(n) 去掉常数…

查看吾托帮88.47的docker里的tomcat日志

步骤如下 &#xff08;1&#xff09;ssh &#xff08;2&#xff09;ssh root192.168.88.47 等待输入密码&#xff1a;fytest &#xff08;3&#xff09;pwd #注释&#xff1a;输出/root &#xff08;4&#xff09;docker exec -it wetoband_deploy /bin/bash #注释&#xff1…

nginx实现反向代理实例

1 前言 1.1 演示内容 在服务器上访问nginx端口然后跳转到tomcat服务器 1.2 前提条件 前提条件&#xff1a;利用docker安装好nginx、tomcat、jdk8&#xff08;tomcat运行需要jdk环境&#xff09; 只演示docker安装tomcat&#xff1a; 默认拉取最新版tomcat docker pull t…

【vue2第二十章】vuex使用 (state,mutations,actions,getters)

vuex是什么&#xff1f; Vuex是一个用于Vue.js应用程序的状态管理模式。它允许您在应用程序中管理共享状态&#xff0c;并以可预测的方式进行状态更新。Vuex集成了Vue的响应式系统&#xff0c;使得状态的变化能够自动地更新视图。使用Vuex&#xff0c;您可以将应用程序的状态集…

【论文阅读 07】Anomaly region detection and localization in metal surface inspection

比较老的一篇论文&#xff0c;金属表面检测中的异常区域检测与定位 总结&#xff1a;提出了一个找模板图的方法&#xff0c;使用SIFT做特征提取&#xff0c;姿态估计看差异有哪些&#xff0c;Hough聚类做描述符筛选&#xff0c;仿射变换可视化匹配图之间的关系&#xf…

如何使用ArcGIS Pro自动矢量化道路

对于已经制作好的电子地图&#xff0c;我们可以通过像素识别的方式将其中的要素提取出来&#xff0c;比如本教程要讲到的道路数据&#xff0c;这里为大家介绍一下在ArcGIS Pro中如何自动矢量化道路&#xff0c;希望能对你有所帮助。 栅格计算 在工具箱中点击“Spatial Analys…

【AIGC】Llama2-7B-Chat模型微调

环境 微调框架&#xff1a;LLaMA-Efficient-Tuning 训练机器&#xff1a;4*RTX3090TI (24G显存) python环境&#xff1a;python3.8, 安装requirements.txt依赖包 一、Lora微调 1、准备数据集 2、训练及测试 1&#xff09;创建模型输出目录 mkdir -p models/llama2_7b_chat…

unity gb28181 rtsp 视频孪生图像拉流和矫正插件(一)

目的是为了视频孪生&#xff0c;将视频放到三维里面&#xff0c;如果使用自己写的插件&#xff0c;有更好的灵活性&#xff0c;同时断线重连等等都更好控制了。 1、矫正算法和硬件解码 最好使用opencv制作&#xff0c;可以使用opencv的cuda加速&#xff0c;opencv的编译&…

面试题:RocketMQ 如何保证消息不丢失,如何保证消息不被重复消费?

文章目录 1、消息整体处理过程Producer发送消息阶段手段一&#xff1a;提供SYNC的发送消息方式&#xff0c;等待broker处理结果。手段二&#xff1a;发送消息如果失败或者超时&#xff0c;则重新发送。手段三&#xff1a;broker提供多master模式&#xff0c;即使某台broker宕机…

聚观早报 | 杭州亚运开幕科技感拉满;腾讯官宣启动「青云计划」

【聚观365】9月25日消息 杭州亚运开幕科技感拉满 腾讯官宣启动「青云计划」 FF任命新全球CEO 比亚迪夺得多国销冠 iPhone 15/15 Pro销售低于预期 杭州亚运开幕科技感拉满 杭州第19届亚洲运动会开幕式23日晚在杭州奥体中心主体育馆举行&#xff0c;这届开幕式可谓科技感拉…