Java多线程04——线程通信

快来打我* 2024-03-27 14:54 178阅读 0赞

1 线程通信机制

线程通信指的是不同线程之间可以交换一些实时的数据信息。

线程是操作系统中的独立个体,但这些个体如果不经过特殊处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一。例如之前处理的线程同步,就是一种线程间通信的方式。

当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时,还会使开发人员对线程任务在处理过程中进行有效的把控与监督。

实现线程间的通信方法:

  • wait / notify

这两个方法都是Object类的方法,换句话说,Java为所有的对象都提供了这两个方法。

  • LockCondition

从JAVA5开始,提供了 Lock 机制,同时还有用于处理 Lock 机制通信控制的 Condition 接口。

2 线程通信的 waitnotify 机制

  • 等待/通知机制

是指线程A调用了对象的 wait() 方法进入到等待状态,而线程B调用了对象的 notify()notifyAll() 方法,线程A收到通知后退出等待队列,进入到可运行状态,进而执行后续操作。

  • 从功能上来说,wait 就是线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的 notify() 唤醒该线程,才能继续获取对象锁,并继续执行。
  • wait()notify() 方法是Object的方法,即所有对象都拥有该方法。

    public class PrintChar {

    1. private boolean flag = false;
    2. public void printA(){
    3. synchronized (this) {
    4. while (true) {
    5. if(flag){
    6. try {
    7. this.wait();
    8. } catch (InterruptedException e) {
    9. e.printStackTrace();
    10. }
    11. }
    12. try {
    13. Thread.sleep(500);
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. System.out.println(Thread.currentThread().getName() + " 输出A");
    18. flag = true;
    19. this.notify();
    20. }
    21. }
    22. }
    23. public void printB(){
    24. synchronized (this) {
    25. while (true) {
    26. if(!flag){
    27. try {
    28. this.wait();
    29. } catch (InterruptedException e) {
    30. e.printStackTrace();
    31. }
    32. }
    33. try {
    34. Thread.sleep(500);
    35. } catch (InterruptedException e) {
    36. e.printStackTrace();
    37. }
    38. System.out.println(Thread.currentThread().getName() + " 输出B");
    39. flag = false;
    40. this.notify();
    41. }
    42. }
    43. }

    }

    class Thread1 extends Thread {

    1. PrintChar pc;
    2. public Thread1(PrintChar pc){
    3. this.pc = pc;
    4. }
    5. @Override
    6. public void run() {
    7. pc.printA();
    8. }

    }

    class Thread2 extends Thread {

    1. PrintChar pc;
    2. public Thread2(PrintChar pc){
    3. this.pc = pc;
    4. }
    5. @Override
    6. public void run() {
    7. pc.printB();
    8. }

    }
    复制代码

测试类

  1. public class TestWait {
  2. public static void main(String[] args) {
  3. PrintChar pc = new PrintChar();
  4. new Thread1(pc).start();
  5. new Thread2(pc).start();
  6. }
  7. }
  8. 复制代码

输出效果如下:

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

过程如下图所示:

8fc3003cc3f04f50ae55aaea27e39092.png

3 线程通信的 LockCondition 机制

Lock 用于控制多线程对需要竞争的共享资源的顺序访问,保证该状态的连续性。

Condition 是 Java 提供的来实现等待/通知的类,Condition 对象是由 Lock 对象所创建。

Condition 中的 await() 方法相当于 Object 的 wait() 方法,Condition 中的 signal() 方法相当于 Object 的 notify() 方法。

使用 LockCondition 机制改写上边的类

  1. import java.util.concurrent.locks.Condition;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;
  4. public class PrintChar2 {
  5. private boolean flag = false;
  6. //创建锁
  7. Lock lock = new ReentrantLock();
  8. //创建监视器
  9. Condition condition = lock.newCondition();
  10. public void printA(){
  11. while (true) {
  12. lock.lock();
  13. if(flag){
  14. try {
  15. condition.await();
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. try {
  21. Thread.sleep(500);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. System.out.println(Thread.currentThread().getName() + " 输出A");
  26. flag = true;
  27. condition.signal();
  28. lock.unlock();
  29. }
  30. }
  31. public void printB(){
  32. while (true) {
  33. lock.lock();
  34. if(!flag){
  35. try {
  36. condition.await();
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. try {
  42. Thread.sleep(500);
  43. } catch (InterruptedException e) {
  44. e.printStackTrace();
  45. }
  46. System.out.println(Thread.currentThread().getName() + " 输出B");
  47. flag = false;
  48. condition.signal();
  49. lock.unlock();
  50. }
  51. }
  52. }
  53. class Thread11 extends Thread {
  54. PrintChar2 pc;
  55. public Thread11(PrintChar2 pc){
  56. this.pc = pc;
  57. }
  58. @Override
  59. public void run() {
  60. pc.printA();
  61. }
  62. }
  63. class Thread22 extends Thread {
  64. PrintChar2 pc;
  65. public Thread22(PrintChar2 pc){
  66. this.pc = pc;
  67. }
  68. @Override
  69. public void run() {
  70. pc.printB();
  71. }
  72. }
  73. 复制代码

测试类

  1. public class TestWait {
  2. public static void main(String[] args) {
  3. PrintChar2 pc = new PrintChar2();
  4. new Thread11(pc).start();
  5. new Thread22(pc).start();
  6. }
  7. }
  8. 复制代码

输出效果如下:

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

Thread-0 输出A

Thread-1 输出B

需要注意的是: 如果使用 Lock 实现锁机制,需要替换原来的 synchronized 代码块,同时加锁和解锁都需要手动操作。二者略有不同。

5525b826a4414d65a978d2d31e7c6542.png

发表评论

表情:
评论列表 (有 0 条评论,178人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java线04——线通信

    1 线程通信机制 线程通信指的是不同线程之间可以交换一些实时的数据信息。 线程是操作系统中的独立个体,但这些个体如果不经过特殊处理就不能成为一个整体,线程间的通信就成为

    相关 线12/线通信

    线程通信的例子:使用两个线程打印1-100。线程1,线程2交替打印 前置知识: 1. wait(); 一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。

    相关 Java 线-线通信

    最近,美美非常的爱吃栗子,剥栗子却有些麻烦,这个任务理所当然的交给了帅帅,每一次,帅帅都会把热气腾腾的栗子剥好,然后放进一个盘子里,而美美每次都会从盘子里拿一个栗子吃: !

    相关 线(3)- 线通信

    线程之间的通信: 多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制。 等待唤醒机...