《五》多线程基础——Java线程间的通信(互斥与协作)
创始人
2024-03-24 16:19:41
0

Java并发编程系列文章
《一》多线程基础——Java线程与进程的基本概念
《二》多线程基础——Java线程入门类和接口
《三》多线程基础——Java线程组和线程优先级
《四》多线程基础——Java线程生命周期及转换
《五》多线程基础——Java线程间的通信(互斥与协作)
《六》实际应用——如何优雅的关闭线程
《七》实际应用——生产者与消费者模型

  并发编程(多线程)一直以来都是程序员头疼的难题。曾经听别人总结过并发编程的第一原则,那就是不要写并发程序,哈哈哈。后来发现,这样能够显著提高程序响应和吞吐量的利器,哪还能忍得住不会用呢?
  整理出《Java并发编程系列文章》,共计7篇,与君共勉。


《五》多线程基础——Java线程间的通信(互斥与协作)

  • 1、锁与同步
  • 2、等待和通知
  • 3、信号量
  • 4、管道
  • 5、其他互斥与协作方法
    • 5.1、sleep()
    • 5.2、join()
    • 5.3、interrupt()
    • 5.4、ThreadLocal类


1、锁与同步

  在Java中,锁的概念都是基于对象的,所以我们⼜经常称它为对象锁。线程同步听着很高大上,cao,被吓了一跳,其实就是让线程之间按照⼀定的顺序执⾏。怎么实现呢?我们可以使⽤锁来实现它。

public class ObjectLock {private static Object lock = new Object();static class ThreadA implements Runnable {@Overridepublic void run() {synchronized (lock) {for (int i = 0; i < 100; i++) {System.out.println("Thread A " + i);}}}}static class ThreadB implements Runnable {@Overridepublic void run() {synchronized (lock) {for (int i = 0; i < 100; i++) {System.out.println("Thread B " + i);}}}}public static void main(String[] args) throws InterruptedException {new Thread(new ThreadA()).start();Thread.sleep(10);new Thread(new ThreadB()).start();}
}

  这⾥声明了⼀个名字为 lock 的对象锁。我们在 ThreadA 和ThreadB 内需要同步的代码块⾥,都是⽤ synchronized 关键字加上了同⼀个对象锁 lock 。
  根据线程和锁的关系,同⼀时间只有⼀个线程持有⼀个锁,那么线程B就会等线程A执⾏完成后释放 lock ,线程B才能获得锁 lock 。
  这⾥在主线程⾥使⽤sleep⽅法睡眠了10毫秒,是为了防⽌线程B先得到锁。因为如果同时start,线程A和线程B都是出于就绪状态,操作系统可能会先让B运⾏。这样就会先输出B的内容,然后B执⾏完成之后⾃动释放锁,线程A再执⾏。

2、等待和通知

  上⾯⼀种基于“锁”的⽅式,线程需要不断地去尝试获得锁,如果失败了,再继续尝试。这可能会耗费服务器资源。⽽等待/通知机制是另⼀种⽅式。
  Java多线程的等待/通知机制是基于 Object 类的 wait() ⽅法和 notify() ,notifyAll() ⽅法来实现的。notify()⽅法会随机叫醒⼀个正在等待的线程,⽽notifyAll()会叫醒所有正在等待的线程。

例如:线程A持有了⼀个锁 lock 并开始执⾏,它可以使⽤ lock.wait() 让⾃⼰进⼊等待状态。这个时
候, lock 这个锁是被释放了的。线程B获得了 lock 这个锁并开始执⾏,它可以在某⼀时刻,使
⽤ lock.notify() ,叫醒之前释放 lock 锁并进⼊等待状态的线程A,注意,此时锁依然在线程B手中,只有当线程B执行完了,线程A才能竞争lock 锁。

public class WaitAndNotify {private static Object lock = new Object();static class ThreadA implements Runnable {@Overridepublic void run() {synchronized (lock) {for (int i = 0; i < 5; i++) {try {System.out.println("ThreadA: " + i);lock.notify();lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}lock.notify();}}}static class ThreadB implements Runnable {@Overridepublic void run() {synchronized (lock) {for (int i = 0; i < 5; i++) {try {System.out.println("ThreadB: " + i);lock.notify();lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}lock.notify();}}}public static void main(String[] args) throws InterruptedException {new Thread(new ThreadA()).start();Thread.sleep(1000);new Thread(new ThreadB()).start();}
}
// 输出:
ThreadA: 0ThreadB: 0ThreadA: 1ThreadB: 1ThreadA: 2ThreadB: 2ThreadA: 3ThreadB: 3ThreadA: 4ThreadB: 4

在这个Demo⾥,线程A和线程B⾸先打印出⾃⼰需要的东⻄,然后使⽤ notify() ⽅法叫醒另⼀个正在等待的线程,然后⾃⼰使⽤ wait() ⽅法陷⼊等待并释放 lock 锁。

需要注意的是等待/通知机制使⽤的是使⽤同⼀个对象锁,如果你两个线程使 ⽤的是不同的对象锁,那它们之间是不能⽤等待/通知机制通信的。

3、信号量

等待后续补充

4、管道

等待后续补充

5、其他互斥与协作方法

5.1、sleep()

  • sleep是Thread的方法,wait是Object的方法。
  • wait释放cpu资源,同时释放锁;sleep释放cpu资源,但是不释放锁,所以易死锁。
  • wait可以指定时间,也可以不指定;⽽sleep必须指定时间。
  • wait必须放在同步块或同步⽅法中,⽽sleep可以再任意位置。

5.2、join()

  • 执行join语句的当前线程,会等被join的线程执行完,再执行。
  • 例如:start httpServer,启动的线程会随着主线程结束后自动挂掉,所以通过。

5.3、interrupt()

  • 线程自己不能interrupt本身,但可以中断别的线程。被调用interrupt方法进行中断的线程如果正处于wait,sleep,join状态,那么会报InterruptedException。
  • 特别注意interrupt正处于join的线程时,interrupt的不是被调用join的线程,而是调用join的线程。
  • interrupt和interrupted的区别:interrupt()用于继承Thread的线程,Thread.interrupted()用于实现Runnable的线程

5.4、ThreadLocal类

  • 如果开发者希望将类的某个静态变量(user ID或者transaction ID)与线程状态关联,则可以考虑使⽤ThreadLocal。
  • 最常⻅的ThreadLocal使⽤场景为⽤来解决数据库连接、Session管理等。数据库连接和Session管理涉及多个复杂对象的初始化和关闭。
  • 如果在每个线程中声明⼀些私有变量来进⾏操作,那这个线程就变得不那么“轻量”了,需要频繁的创建和关闭连接。

相关内容

热门资讯

无惧苹果起诉,线人放出iPho... 据科技媒体 Phone Arena 昨天报道,在今年 7 月被苹果起诉后,爆料人 Jon Pross...
民间借贷纠纷:选靠谱律师,彭艳... 在民间借贷纠纷频发的当下,寻找一位专业、靠谱且性价比高的律师至关重要。民间借贷纠纷涉及的法律问题复杂...
大烨智能刚收到立案告知书,律师... 雷达财经雷助吧出品 文|阑珊 编|深海 12月26日,大烨智能发布《关于收到中国证券监督管理委员会立...
推荐靠谱高性价比离婚纠纷律师:... 在人生的旅途中,离婚纠纷往往是一个令人痛苦且棘手的难题。当面临离婚时,涉及财产分割、子女抚养权争夺等...
电芯被指存在质量问题!吉利子公... 12月26日,欣旺达发布公告,公司子公司欣旺达动力于2025年12月25日收到浙江省宁波市中级人民法...
吉利旗下公司起诉欣旺达:“交付... 截至目前,国内罕有因交付电芯出现质量问题而和客户对簿公堂的动力电池制造商。老牌锂电企业欣旺达电子股份...
八位专家点评2025年劳动法律... 2025年劳动法律监督 “一函两书”典型案例专家点评 12月25日,中华全国总工会联合最高人民法院、...
全国人大常委会:对104件法律... 全国人民代表大会常务委员会关于批准《全国人民代表大会常务委员会法制工作委员会关于法律清理工作情况和处...
全国人民代表大会常务委员会关于... 新华社北京12月27日电 全国人民代表大会常务委员会关于《中华人民共和国刑事诉讼法》第二百九十二条的...