线程间通信

打印 上一主题 下一主题

主题 905|帖子 905|积分 2719

线程间通信

多线程编程步骤(中)

第一,创建资源类,创建属性和操作方法;第二,在资源操作方法,1)判断 2)工作 3)通知;第三,创建多线程调用资源类的方法。
案例

要求,有两个线程,实现对一个初始值为0的变量,一个线程对值+1,一个线程对值-1。
代码实现
  1. /**
  2. * @author 长名06
  3. * @version 1.0
  4. * 线程通信案例 两个线程对一个值进行 decr incr
  5. * 用synchronized关键字实现
  6. */
  7. class Share {
  8.     private int number;
  9.     public synchronized void incr() throws InterruptedException {
  10.         /**
  11.          * 这样写,会出现虚假唤醒问题,因为如果当前线程被等待,然后被唤醒时,if语句,就不会再次进行判断
  12.          * 有可能出现,此时的number != 0 当时依旧进行了 +1操作 减方法类似
  13.          * wait()方法再api文档中,就提醒,在一个参数版本中,中断和虚假唤醒是可能的,并且该方法应该始终在循环中使用:
  14.          * 线程在哪里被阻塞就会在哪里,被唤醒,也就是说线程被阻塞时,是满足number!= 0,所以阻塞,但是因为一个线程执行完后,释                  
  15.          * 放锁,然后唤醒等待的线程,是随机唤醒的,有可能当前+1的条件依旧不满足,但是系统却唤醒了该线程,因为是if语句,在                         
  16.          * this.wait()处被唤醒,程序继续执行,导致其实条件不满足,却执行了+1操作,所以使用while()循环进行判断,只能当条件满                  
  17.          * 足且线程被唤醒才执行incr方法
  18.          * if (number != 0){//条件
  19.          *    this.wait();
  20.          * }
  21.          */
  22.         while (number != 0) {
  23.             this.wait();
  24.         }
  25.         //加1
  26.         number++;
  27.         System.out.println(Thread.currentThread().getName() + "\t" + number);
  28.         //通知其他线程
  29.         this.notifyAll();
  30.     }
  31.     public synchronized void decr() throws InterruptedException {
  32.         while (number != 1) {
  33.             this.wait();
  34.         }
  35.         //减1
  36.         number--;
  37.         System.out.println(Thread.currentThread().getName() + "\t" + number);
  38.         //通知其他线程
  39.         this.notifyAll();
  40.     }
  41. }
  42. public class ThreadDemo {
  43.     public static void main(String[] args) {
  44.         Share share = new Share();
  45.         new Thread(() -> {
  46.             for (int i = 0; i < 25; i++) {
  47.                 try {
  48.                     share.incr();
  49.                 } catch (InterruptedException e) {
  50.                     e.printStackTrace();
  51.                 }
  52.             }
  53.         }, "aa").start();
  54.         new Thread(() -> {
  55.             for (int i = 0; i < 25; i++) {
  56.                 try {
  57.                     share.decr();
  58.                 } catch (InterruptedException e) {
  59.                     e.printStackTrace();
  60.                 }
  61.             }
  62.         }, "bb").start();
  63.     }
  64. }
复制代码
多线程编程步骤(下)

第一,创建资源类,创建属性和操作方法;第二,在资源操作方法,1) 判断 2)工作 3)通知;第三,创建多线程调用资源类的方法;第四,防止虚假唤醒问题。
Lock实现上述案例

代码
  1. import java.util.concurrent.locks.Condition;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;
  4. /**
  5. * @author 长名06
  6. * @version 1.0
  7. */
  8. //第一步创建资源类,属性和操作方法
  9. class ShareByLock {
  10.     private int number;
  11.     //获得锁
  12.     private final ReentrantLock lock = new ReentrantLock();
  13.     //为当前锁,创建一个新的condition,并绑定到该锁上
  14.     private Condition condition = lock.newCondition();
  15.     public void incr() throws InterruptedException {
  16.         //上锁
  17.         lock.lock();
  18.         //第二步 进行
  19.         // 1.判断(线程切换的条件)
  20.         // 2.执行(线程执行的具体操作)
  21.         // 3.通知(唤醒等待的其他线程)
  22.         try {
  23.             //判断
  24.             //第四步 防止虚假唤醒现象
  25.             while (number != 0) {
  26.                 condition.await();
  27.             }
  28.             //执行
  29.             number++;
  30.             System.out.println(Thread.currentThread().getName() + "\t" + number);
  31.             //通知
  32.             condition.signalAll();
  33.         } finally {
  34.             //解锁
  35.             lock.unlock();
  36.         }
  37.     }
  38.     public void decr() throws InterruptedException {
  39.         //上锁
  40.         lock.lock();
  41.         try {
  42.             //判断
  43.             while (number != 1) {
  44.                 condition.await();
  45.             }
  46.             //执行
  47.             number--;
  48.             System.out.println(Thread.currentThread().getName() + "\t" + number);
  49.             //通知
  50.             condition.signalAll();
  51.         } finally {
  52.             //解锁
  53.             lock.unlock();
  54.         }
  55.     }
  56. }
  57. public class ThreadDemoByLock {
  58.     public static void main(String[] args) {
  59.         ShareByLock shareByLock = new ShareByLock();
  60.         //第三步 创建多个线程调用资源类的方法
  61.         new Thread(() -> {
  62.             for (int i = 0; i < 10; i++) {
  63.                 try {
  64.                     shareByLock.incr();
  65.                 } catch (InterruptedException e) {
  66.                     e.printStackTrace();
  67.                 }
  68.             }
  69.         }, "aa").start();
  70.         new Thread(() -> {
  71.             for (int i = 0; i < 10; i++) {
  72.                 try {
  73.                     shareByLock.decr();
  74.                 } catch (InterruptedException e) {
  75.                     e.printStackTrace();
  76.                 }
  77.             }
  78.         }, "bb").start();
  79.         new Thread(() -> {
  80.             for (int i = 0; i < 10; i++) {
  81.                 try {
  82.                     shareByLock.incr();
  83.                 } catch (InterruptedException e) {
  84.                     e.printStackTrace();
  85.                 }
  86.             }
  87.         }, "cc").start();
  88.         new Thread(() -> {
  89.             for (int i = 0; i < 10; i++) {
  90.                 try {
  91.                     shareByLock.decr();
  92.                 } catch (InterruptedException e) {
  93.                     e.printStackTrace();
  94.                 }
  95.             }
  96.         }, "dd").start();
  97.     }
  98. }
复制代码
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

刘俊凯

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表