线程通信

当线程在系统中运行时,线程的调度具有一定的透明性,程序通常无法准确控制线程的轮换执行,但Java 也提供了一些机制来保证线程协调运行。
本文包含:

  1. 传统的线程通信
  2. 使用 Condition 控制线程通信
  3. 使用阻塞队列(BlockingQueue)控制线程通信

1. 传统的线程通信

传统的线程通信为实现重复存款、取钱的动作,可以借助于Object 类提供的 wait()、notify()、notifyAll() 三个方法,这三个方法并不属于 Thread 类,而是属于 Object 类。但这三个方法必须由同步监视器对象来调用,这可以分成以下两种情况。
在这里插入图片描述
关于这三个方法的解释如下。
在这里插入图片描述
程序中可以通过一个旗标来标识账户中是否已有存款,当旗标为 false 时,表明账户中没有存款,存款者线程可以向下执行,当存款者把钱存入账户后,将旗标设为 true,并调用 notify() 或 notifyAll() 方法来唤醒其他进程;当存款者线程进入线程体后,如果旗标为 true 就调用 wait() 方法让该线程等待。

当旗标为 true 时,表明账户中已经存入了存款。则取钱者线程可以向下执行,当取钱者把钱从账户中取出后,将旗标设为 false() ,并调用 notify() 或 notifyAll() 方法来唤醒其他线程;当取钱者线程进入线程体后,如果旗标为 false 就调用 wait() 方法让该线程等待。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
上面程序中的粗体字代码使用了 wait() 和 notifyAll() 进行了控制,对存款者线程而言,当程序进入 deposit() 方法后,如果 flag 为 true,则表明账户中已有存款,程序调用 wait()方法阻塞;否则程序向下执行存款操作,当存款操作执行完成后,系统将 flag 设为 true,然后调用 notifyAll() 来唤醒其他被阻塞的线程—如果系统中有存款者线程,存款者线程也会被唤醒,当爱存款者线程执行到 1 号代码处再次进入阻塞状态,只有执行 draw() 方法的取钱者线程才可以向下执行。

程序中的存款者线程循环 100 次重复存款,而取钱者线程则循环 100 次重复取钱,存款者线程和取钱者线程分别调用 Account 对象的 deposit()、draw() 方法来实现。
在这里插入图片描述在这里插入图片描述在这里插入图片描述
主程序可以启动任意多个存款线程和取钱线程,可以看到所以的取钱线程都必须等存款线程存钱后才可以向下执行,而存款线程也必须等到取钱线程取钱后才可以向下执行。

2. 使用 Condition 控制线程通信

如果程序不使用 synchronized 关键字来保持同步,而是直接使用 Lock 对象来保证同步,则系统中不存在隐式的同步监视器,也就不能使用 wait()、notify()、notifyAll() 方法来进行线程通信了。

当使用 Lock 对象来保持同步时,Java 提供了一个 condition 类来保持协调,使用 condition 可以让那些已经得到 Lock 对象却无法继续执行的线程释放 Lock 对象,Condition 对象也可以唤醒其他处于等待的线程。
在这里插入图片描述
在这里插入图片描述
下面程序中 Account 使用 Lock 对象来控制同步,并使用 Condition 对象来控制线程的协调运行。在这里插入图片描述在这里插入图片描述

3. 使用阻塞队列(BlockingQueue)控制线程通信

BlockingQueue 也是 Queue 的子接口,但他的主要用途并不是作为容器,而是作为线程同步的工具。Blocking 具有严格特征:当生产者线程试图向BlockingQueue 中取出元素时,如果队列已空,则该线程被阻塞。

程序的两个线程通过交替向 BlockingQueue 中放入元素、取出元素,即可很好的控制线程的通信。
BlockingQueue 提供如下两个支持阻塞的方法。
在这里插入图片描述在这里插入图片描述
BlockingQueue 继承了 Queue 接口,当然也可使用 Queue 接口中的方法,这些方法可以归纳为如下三组:
在这里插入图片描述
BlockingQueue 包含的方法之间的对应关系如下表所示:
在这里插入图片描述
BlockingQueue 与其实现类之间的类图如下图所示:
在这里插入图片描述
从上图可以看出,BlockingQueue 包含如下 5 个实现类。
在这里插入图片描述
下面以 ArrayBlockingQueue 为例介绍阻塞队列的功能和用法。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值