多线程基础:线程通信内容补充

多线程基础:线程通信内容补充


文章目录

  • 多线程基础:线程通信内容补充
  • 前言
  • 一、wait(), notify(), notifyAll()
  • 二、join()
  • 三、Lock 和 Condition
  • 四、并发集合和原子变量
    • 1、并发集合
    • 2、原子变量
  • 总结


前言

前文内容中讲了线程通信的内容,但是不够完善,所以这边文章是针对那部分的内容的一个补充说明。

在Java中,线程之间的通信主要有几种方式,包括使用共享变量、wait()/notify()/notifyAll()方法、join()方法、Lock和Condition接口,以及并发集合和原子变量等。


一、wait(), notify(), notifyAll()

这些方法属于Object类,用于在同步块或同步方法中实现线程间的通信。

  1. wait(): 使当前线程等待,直到其他线程调用此对象的notify()或notifyAll()方法。
  2. notify(): 唤醒在此对象监视器上等待的单个线程。
  3. notifyAll(): 唤醒在此对象监视器上等待的所有线程。
public class WaitNotifyExample {  private static final Object lock = new Object();  private static boolean ready = false;  public static void main(String[] args) {  Thread t1 = new Thread(() -> {  synchronized (lock) {  while (!ready) {  try {  lock.wait();  } catch (InterruptedException e) {  e.printStackTrace();  }  }  System.out.println("Thread 1 is running");  }  });  Thread t2 = new Thread(() -> {  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  e.printStackTrace();  }  synchronized (lock) {  ready = true;  lock.notifyAll();  }  });  t1.start();  t2.start();  }  
}

在这个例子中,线程1先获取到lock锁,然后开始循环,在第一次循环就调用了wait()方法,使线程进入等待状态,也就释放了锁,cpu时间片切到线程2,线程2获取到锁之后,讲ready设置为true同时唤醒其他所有线程,线程1进行运行状态,重新进行遍历判断,此时判断内容为false,所以线程1执行结束。

二、join()

join()方法是Thread类的一个方法,它使当前执行线程等待,直到调用join()方法的线程执行完毕。

public class JoinExample {  public static void main(String[] args) throws InterruptedException {  Thread t1 = new Thread(() -> {  for (int i = 0; i < 5; i++) {  System.out.println("Thread 1: " + i);  try {  Thread.sleep(500);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  });  t1.start();  t1.join(); // 等待t1线程执行完毕  for (int i = 0; i < 5; i++) {  System.out.println("Main thread: " + i);  }  }  
}

在这个例子中,主线程会等待线程t1执行完毕后再继续执行。

三、Lock 和 Condition

Lock接口及其实现(如ReentrantLock)以及Condition接口提供了比synchronized和wait()/notify()更灵活和强大的线程同步机制。

import java.util.concurrent.locks.Condition;  
import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReentrantLock;  public class LockConditionExample {  private final Lock lock = new ReentrantLock();  private final Condition condition = lock.newCondition();  private boolean ready = false;  public void waitForSignal() throws InterruptedException {  lock.lock();  try {  while (!ready) {  condition.await(); // 等待信号  }  System.out.println("Received signal");  } finally {  lock.unlock();  }  }  public void signal() {  lock.lock();  try {  ready = true;  condition.signalAll(); // 发送信号  } finally {  lock.unlock();  }  }  public static void main(String[] args) throws InterruptedException {  LockConditionExample example = new LockConditionExample();  Thread t1 = new Thread(example::waitForSignal);  t1.start();  Thread.sleep(1000); // 让t1先开始执行并等待  example.signal(); // 发送信号给t1  }  
}

在这个例子中,waitForSignal方法中的线程会等待signal方法发送信号。

四、并发集合和原子变量

1、并发集合

Java的java.util.concurrent包提供了许多线程安全的集合类,如ConcurrentHashMap、CopyOnWriteArrayList等。这些集合内部实现了必要的同步机制,使得多个线程可以安全地并发访问它们。

import java.util.concurrent.ConcurrentHashMap;  public class ConcurrentHashMapExample {  private static final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();  public static void main(String[] args) {  Thread t1 = new Thread(() -> {  map.put("key1", 1);  System.out.println("Thread 1 put key1: " + map.get("key1"));  });  Thread t2 = new Thread(() -> {  map.put("key2", 2);  System.out.println("Thread 2 put key2: " + map.get("key2"));  });  t1.start();  t2.start();  }  
}

在这个例子中,两个线程可以并发地向ConcurrentHashMap中添加元素,而无需添加额外的同步锁。

2、原子变量

原子变量类(如AtomicInteger、AtomicLong、AtomicBoolean等)提供了在并发编程中原子地更新变量的方法。原子操作是不可中断的,即在多线程环境下,当一个线程在执行原子操作时,其他线程无法访问该变量,从而保证了线程安全。

import java.util.concurrent.atomic.AtomicInteger;  public class AtomicIntegerExample {  private static final AtomicInteger counter = new AtomicInteger(0);  public static void main(String[] args) throws InterruptedException {  Thread t1 = new Thread(() -> {  for (int i = 0; i < 5; i++) {  counter.incrementAndGet(); // 原子地增加计数器的值  System.out.println("Thread 1 counter: " + counter.get());  }  });  Thread t2 = new Thread(() -> {  for (int i = 0; i < 5; i++) {  counter.incrementAndGet(); // 原子地增加计数器的值  System.out.println("Thread 2 counter: " + counter.get());  }  });  t1.start();  t2.start();  t1.join();  t2.join();  System.out.println("Final counter value: " + counter.get());  }  
}

在这个例子中,两个线程都尝试原子地增加同一个AtomicInteger的值,无需额外的同步。


总结

  1. wait()/notify()/notifyAll()是基于对象监视器的传统线程通信方式,需要配合synchronized关键字使用。
  2. join()用于让一个线程等待另一个线程完成其执行。
  3. Lock和Condition提供了更灵活和强大的线程同步机制,能够更精细地控制线程间的通信和协作。
  4. 并发集合和原子变量简化了多线程编程中的同步问题,使得开发者能够更轻松地编写线程安全的代码。

在选择使用哪种线程通信方式时,需要根据具体的场景和需求来决定。例如,对于简单的等待/通知场景,wait()/notify()可能足够;对于需要更精细控制的场景,Lock和Condition可能更合适;而对于只需要原子更新变量的场景,原子变量类则是最简单的选择。

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

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

相关文章

企业网站建设的方法的相关问题的解决办法的问题

现在市场上比较大的公司都建立了自己的企业网站&#xff0c;比如华为、小米等&#xff0c;在他们的企业网站中&#xff0c;可以充分展示自己产品的优势&#xff0c;介绍公司的优质服务。 这都是让顾客改变购买想法的重要因素。 现在互联网发达了&#xff0c;很多人在购买产品的…

Typescript再学习-接口interface扩展(5)

接口可以通过extends继承&#xff0c;看代码如下 interface commonPerson {name: string;age: number;sex: string;address: string; }interface Police extends commonPerson {idCard: string;job: string; } let LiHanxing: Police {name: "李汉星",age: 22,sex:…

智慧工地安全生产与风险预警大平台的构建,需要哪些技术?

随着科技的不断发展&#xff0c;智慧工地已成为现代建筑行业的重要发展趋势。智慧工地方案是一种基于先进信息技术的工程管理模式&#xff0c;旨在提高施工效率、降低施工成本、保障施工安全、提升施工质量。一般来说&#xff0c;智慧工地方案的构建&#xff0c;需要通过集成物…

计算机网络:物理层 - 信道极限容量

计算机网络&#xff1a;物理层 - 信道极限容量 实际信道中的数字信号奈式准则香农公式练习 实际信道中的数字信号 信号在传输过程中会受到各种因素的影响&#xff0c;如图所示&#xff1a; 这是一个数字信号&#xff0c;当它通过实际的信道后&#xff0c;波形会产生失真&#…

java中正则表达式第一次特殊使用

记录第一次使用~ 正则表达式的使用 正则表达式&#xff08;Regular Expression&#xff09;是一种用于模式匹配的强大工具&#xff0c;它由普通字符&#xff08;例如字母、数字、符号&#xff09;和特殊字符&#xff08;元字符&#xff09;组成。以下是使用正则表达式的一些…

Flutter 内置按钮介绍及使用

Flutter 提供了多种内置按钮&#xff0c;可以满足不同场景的需求。本文将介绍 Flutter 中常见的按钮类型&#xff0c;以及它们的属性和使用方法。 按钮类型 Flutter 中常见的按钮类型包括&#xff1a; ElevatedButton: 凸起按钮&#xff0c;默认带有阴影和灰色背景。TextBut…

如何使用C语言进行异常处理?C语言中的可变参数函数

一、如何使用C语言进行异常处理&#xff1f; 在C语言中&#xff0c;并没有像C或Java等语言那样内置的异常处理机制。C语言主要依赖于返回值、错误码以及条件编译指令来进行错误处理。然而&#xff0c;你仍然可以通过一些方法模拟异常处理的行为。 一种常见的模拟异常处理的方…

Linux学习:进程(3)与 环境变量

目录 1. 进程的优先级1.1 什么是进程的优先级1.2 优先级的具体表示与查看方式 2. 进程的切换与调度2.1 切换2.2 调度 3. 环境变量3.1 main参数/命令行参数3.2 什么是环境变量3.3 环境变量的使用与特性3.5 本地变量与环境变量的脚本配置文件 1. 进程的优先级 在计算机运行的过程…

stamac Ethernet DTS配置

目录 Demo 配置 compatible reg interrupts & interrupt-names phy-mode phy-handle Snps,reset-gpio

【JavaScript】数组 ② ( JavaScript 数组索引 | JavaScript 遍历数组 | 使用 for 循环遍历数组 )

文章目录 一、JavaScript 数组索引1、数组索引2、数组索引 - 代码示例 二、JavaScript 遍历数组1、使用 for 循环遍历数组2、使用 for 循环遍历数组 - 代码示例 一、JavaScript 数组索引 1、数组索引 在 JavaScript 中 , 数组 的 " 索引 " 又称为 " 下标 "…

将yolov5s部署到安卓上实战经验总结

最近需要在手机端实现一个目标检测的功能&#xff0c;于是选择了小巧又在目标检测方面表现很好的yolov5s&#xff0c;官网下载yolov5代码&#xff0c;用自己做的数据集进行了训练&#xff0c;然后把模型转换成torchscript格式&#xff0c;这些过程网上都有很多讲解&#xff0c;…

电脑突然死机怎么办?

死机是电脑常见的故障问题&#xff0c;尤其是对于老式电脑来说&#xff0c;一言不合电脑画面就静止了&#xff0c;最后只能强制关机重启。那么你一定想知道是什么原因造成的吧&#xff0c;一般散热不良最容易让电脑死机&#xff0c;还有系统故障&#xff0c;比如不小心误删了系…

手机卫星通信

1. 前言 手机卫星通信&#xff0c;顾名思义&#xff0c;就是手机可以与卫星建立通信连接实现数据交互的技术。手机卫星高速数据连接是目前手机通话短信的下一代技术&#xff0c;也是新一代通信生态中的重要组成部分&#xff0c;即非地面网络&#xff08;Non-Terrestrial Networ…

React 应用实现监控可观测性最佳实践

前言 React 是一个用于构建用户界面的 JavaScript 框架。它采用了虚拟 DOM 和 JSX&#xff0c;提供了一种声明式的、组件化的编程模型&#xff0c;以便更高效地构建用户界面。无论是简单还是复杂的界面&#xff0c;React 都可以胜任。 YApi 是使用 React 编写的高效、易用、功…

2.人机交互-图形化界面的小故事

文章目录 一、图形化界面的小故事二、什么是cmd&#xff1f; 计算机在刚开始出现的时候&#xff0c;因为占地广、造价高、耗电多&#xff0c;一般都是给军队或者政府使用的&#xff0c;而并不是给个人使用的。然后随着计算机不断地发展&#xff0c;体积越来越小&#xff0c;出现…

【计算机网络篇】数据链路层(4.1)可靠传输的相关概念

文章目录 &#x1f354;可靠传输的相关概念⭐分组丢失⭐分组失序⭐分组重复 &#x1f95a;注意 &#x1f354;可靠传输的相关概念 使用差错检测技术&#xff08;例如循环冗余校验CRC&#xff09;&#xff0c;接收方的数据链路层就可以检测出帧在传输过程中是否产生了误码&…

B2902A是德科技B2902A精密型电源

181/2461/8938产品概述&#xff1a; Agilent B2902A 精密源/测量单元 (SMU) 是一款 2 通道、紧凑且经济高效的台式 SMU&#xff0c;能够源和测量电压和电流。它用途广泛&#xff0c;可以轻松、高精度地执行 I/V&#xff08;电流与电压&#xff09;测量。4 象限源和测量功能的集…

linux 内存介绍

大致共有四类&#xff1a;VSS、RSS、PSS、USS &#xff0c;通常情况下&#xff0c;VSS > RSS > PSS > USS 1.VSS(Virtual Set Size)虚拟耗用内存&#xff08;包含共享库占用的内存&#xff09; VSS表示一个进程可访问的全部内存地址空间的大小。这个大小包括了进程已…

单例模式如何保证实例的唯一性

前言 什么是单例模式 指一个类只有一个实例&#xff0c;且该类能自行创建这个实例的一种创建型设计模式。使用目的&#xff1a;确保在整个系统中只能出现类的一个实例&#xff0c;即一个类只有一个对象。对于频繁使用的对象&#xff0c;“忽略”创建时的开销。特点&#xff1a…

Netty对Channel事件的处理以及空轮询Bug的解决

继续上一篇Netty文章&#xff0c;这篇文章主要分析Netty对Channel事件的处理以及空轮询Bug的解决 当Netty中采用循环处理事件和提交的任务时 由于此时我在客户端建立连接&#xff0c;此时服务端没有提交任何任务 此时select方法让Selector进入无休止的阻塞等待 此时selectCnt进…