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

【Java】JUC并发(线程的方法、多线程的同步并发)

线程的方法

一、线程的插队:join()方法

1、作用

        暂停当前线程的执行,直到调用join()的目标线程执行完毕,但不影响同一时刻的其他线程。

// 使用join()
public class Test01 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{System.out.println("子线程 => begin");try {Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("子线程 => end");});t.start();// t线程插队到主线程(当前线程)前面// t线程结束后,主线程才会继续执行// t.join() 相当于 t.join(0 )t.join();System.out.println("主线程 => end");}
}子线程 => begin
子线程 => end
主线程 => end

// 不使用join()
public class Test01 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{System.out.println("子线程 => begin");try {Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("子线程 => end");});t.start();// t线程插队到主线程(当前线程)前面// t线程结束后,主线程才会继续执行// t.join() 相当于 t.join(0 )
//        t.join();System.out.println("主线程 => end");}
}主线程 => end
子线程 => begin
子线程 => end

2、重载形式

  • join() : 无限等待,直到目标线程终止
  • join(long millis):等待指定毫秒,超时不再等待
  • join(long millis, int nanos) :精确到纳秒,超时不再等待

3、使用场景(多个线程要求按序执行)

public class Test02 {public static void main(String[] args) {Thread t1 = new Thread(()->{for (int i = 0;i<5;i++){System.out.println(Thread.currentThread().getName() + "->" + i);}},"数字线程");Thread t2 = new Thread(()->{try {// 等待t1线程完成t1.join();} catch (InterruptedException e) {throw new RuntimeException(e);}for (char i = 'A';i<'E';i++){System.out.println(Thread.currentThread().getName() + "->" + i);}},"字母线程");Thread t3 = new Thread(()->{try {// 等待t2线程完成t2.join();} catch (InterruptedException e) {throw new RuntimeException(e);}for (char i = 'A';i<'E';i++){System.out.println(Thread.currentThread().getName() + "->" + (char)(Math.random()*100));}},"符号线程");t1.start();t2.start();t3.start();}
}数字线程->0
数字线程->1
数字线程->2
数字线程->3
数字线程->4
字母线程->A
字母线程->B
字母线程->C
字母线程->D
符号线程->I
符号线程->&
符号线程->
符号线程->

4、join()和sleep()的区别

  • join()执行过程中,会释放当前线程的锁;sleep()执行过程中,不会释放当前线程的锁。
  • join()是用过wait/notify机制思想;sleep()通过操作系统的定时器来实现。
  • join()主要实现线程任务编排;sleep()用与模仿耗时操作。

二、线程的中断:interrupt()方法

1、作用

        将该线程的中断状态设置为true,线程的下一步动作取决于中断状态。

2、实现原理

        支持中断的方法(sleep()、join()、wait()等方法)在执行过程中,会监视中断状态,一旦发现其状态为“true”,就会抛出一个中断异常InterruptedException,并给等待状态发出一个中断信号,从而退出等待状态。注意:当线程中没有可以监听中断状态的方法时,interrupt()方法将不起作用。

public class Test03 {public static void main(String[] args) {Thread t = new Thread(()->{// 场景1 : 调用休眠方法(支持中断方法)System.out.println("子线程开始执行!");try {// 子线程休眠4秒Thread.sleep(1000*4);} catch (InterruptedException e) {System.out.println("子线程中断!");return;}System.out.println("子线程结束!");});t.start();try {// 主线程休眠3秒Thread.sleep(1000*3);} catch (InterruptedException e) {throw new RuntimeException(e);}t.interrupt();System.out.println("主线程结束!");}
}当子线程处于休眠状态时,而主线程对子线程进行中断则会子线程中断,不会继续向下执行。子线程开始执行!
主线程结束!
子线程中断!

public class Test03 {public static void main(String[] args) {Thread t = new Thread(()->{// 场景2 : 判断线程的中断状态while (!isinterrupt){System.out.println("子线程开始执行!!");}System.out.println("子线程中断!");});t.start();try {Thread.sleep(1000*3);} catch (InterruptedException e) {throw new RuntimeException(e);}t.interrupt();System.out.println("主线程结束!");}
}当没有使用中断方法时,子线程的中断状态一直时false,while的条件一
直为true会一直执行,当使用了中断方法后,中断状态更新为true,则会
退出while循环继续向下执行。

三、线程的让出:yield()方法

1、作用

        让当前获取CPU的线程,主动让出CPU不执行。

public class demo2 {public static void main(String[] args) {Thread t1 = new Thread(){public void run() {Thread.yield();for (int i = 0;i<5;i++){System.out.println(i);}}};Thread t2 = new Thread(){public void run() {for (char i = 'A';i<'E';i++){System.out.println(i);}}};t1.start();t2.start();}
}

四、守护线程(Daemon Thread)

1、用户线程和守护线程

用户线程:通常为创建的普通线程

守护线程:守护线程执行结束后,虚拟机不会自定退出;而非守护线程执行完毕后,虚拟机会自动退出

2、设置守护线程

        在调用start()方法前,调用setDaemon(true)把该线程标记为守护线程。

Thread t1 = new Thread();
t1.setDaemon(true);
t1.start();

多线程同步并发

一、多线程的数据不一致

        当多个线程同时运行时,线程的调度有操作系统决定,程序本身无法决定。因此,任何一个线程都有可能在任何指令出被系统暂停,然后莫个时间段后继续执行。如果多个线程同时共享一个资源,则会出现数据不一致的问题。

public class Test04 {public static void main(String[] args) {Thread add = new Thread(new AddThread());Thread dec = new Thread(new DecThread());add.start();dec.start();try {add.join();dec.join();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Count.count);}
}
class Count{public static int count = 0; //公共的累加值public static Object lock = new Object(); // 锁对象
}// 累加线程
class AddThread implements Runnable{@Overridepublic void run() {for (int i = 0; i<10000;i++){Count.count += 1;}}}
}
// 累减线程
class DecThread implements Runnable{@Overridepublic void run() {for (int i = 0; i<10000;i++){Count.count -= 1;}}}
}由于算数运算没有原子性所以会出现算数运算被覆盖的情况,从而导致结果不正确
-1234

二、 synchronized关键字

1、什么是synchronized

        Synchronized关键字,也可以理解为一种同步锁。他可以对一段代码进行加锁和解锁,从而使其拥有原子性,从而确保代码的线程安全。

2、synchronized 的用法

  • 修饰实例方法:synchronized 修饰实例方法,则用到的锁,默认为 this 当前方法调用对象;
public class Test05 {public static void main(String[] args) {Foo f1 = new Foo();Foo f2 = new Foo();Thread t1 = new Thread(()->{f1.add();});Thread t2 = new Thread(()->{f1.dec();});t1.start();t2.start();try {t1.join();t2.join();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Foo.counter);}
}
class Foo{public static int counter = 0;public void add(){synchronized (this){for (int i = 0;i<10000;i++){counter++;}}}// 修饰实例方法,使用this关键字做锁public synchronized void dec(){for (int i=0;i<10000;i++){counter--;}}
}
  • 修饰静态方法:synchronized 修饰静态方法,则其所用的锁,默认为 Class 对象;
public class Test05 {public static void main(String[] args) {Foo f1 = new Foo();Foo f2 = new Foo();Thread t1 = new Thread(()->{f1.add();});Thread t2 = new Thread(()->{f1.dec();});t1.start();t2.start();try {t1.join();t2.join();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Foo.counter);}
}
class Foo{public static int counter = 0;public void add(){synchronized (this.getClass()){for (int i = 0;i<10000;i++){counter++;}}}public synchronized static void dec(){for (int i=0;i<10000;i++){counter--;}}
}
  • 修饰代码块:synchronized 修饰代码块,则其所用的锁,是某个指定 Java 对象
public class Test04 {public static void main(String[] args) {Thread add = new Thread(new AddThread());Thread dec = new Thread(new DecThread());add.start();dec.start();try {add.join();dec.join();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Count.count);}
}class Count{public static int count = 0; //公共的累加值public static Object lock = new Object(); // 锁对象
}// 累加线程
class AddThread implements Runnable{@Overridepublic void run() {for (int i = 0; i<10000;i++){// synchronized 同步锁synchronized (Count.lock) {// 加锁// 临界区Count.count += 1;}// 释放锁}}
}// 累减线程
class DecThread implements Runnable{@Overridepublic void run() {for (int i = 0; i<10000;i++){// synchronized 同步锁synchronized (Count.lock) {// 加锁// 临界区Count.count -= 1;}// 释放锁}}
}

http://www.lryc.cn/news/588727.html

相关文章:

  • 微信小程序:在ios中border边框显示不全
  • 飞睿UWB超宽带定位测距技术,数字钥匙重塑智能生活,高精度厘米级定位无感解锁
  • 公网ip到服务器流程
  • 2025年最新香港站群服务器租用价格参考
  • 从零开始的云计算生活——第三十二天,四面楚歌,HAProxy负载均衡
  • 【工程篇】07:如何打包conda环境并拷贝到另一台服务器上
  • Racknerd服务器Ubuntu
  • Datawhale 25年7月组队学习coze-ai-assistant Task1学习笔记:动手实践第一个AI Agent—英伦生活口语陪练精灵
  • 阿里云ssh证书过期,如果更换并上传到服务器
  • 三十二、【核心功能改造】数据驱动:重构仪表盘与关键指标可视化
  • 数学金融与金融工程:学科差异与选择指南
  • uniapp 微信小程序Vue3项目使用内置组件movable-area封装悬浮可拖拽按钮(拖拽结束时自动吸附到最近的屏幕边缘)
  • Springboot儿童认知图文辅助系统6yhkv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • LED 照明应用提供高性价比方案?会是你的首选吗?
  • Unity音游开发全指南:模板与免费资源高效构建节奏游戏
  • labview关于OOP
  • CG--类比推理
  • java截取视频帧
  • 视频HDR技术全解析:从原理到应用的深度探索
  • 音视频学习(三十九):IDR帧和I帧
  • React.FC与React.Component
  • PyCharm 高效入门指南:从安装到效率倍增
  • docker拉取nacos镜像失败
  • lanch4j将jar转成exe
  • 开通保存图片权限
  • iOS高级开发工程师面试——Swift
  • 语言模型玩转3D生成:LLaMA-Mesh开源项目
  • 无人机故障响应模块运行与技术难点
  • 全面安装指南:在Linux、Windows和macOS上部署Apache Cassandra
  • 网络劫持对用户隐私安全的影响:一场无形的数据窃取危机