JUC---05线程间通信(一)
一、普通的线程间通信
1.synchronized实现
package com.jenne.mydemo; class ShareDataOne { private int number = 0; public synchronized void incr() { try { //判断 while (number != 0) { wait(); } //干活 number++; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知 notifyAll(); } catch (Exception e) { e.printStackTrace(); } } public synchronized void decr() { try { //判断 while (number != 1) { wait(); } //干活 number--; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知 notifyAll(); } catch (Exception e) { e.printStackTrace(); } } } public class NotifyWaitDemo { public static void main(String[] args) { ShareDataOne shareDataOne = new ShareDataOne(); //++ new Thread(() -> { for (int i = 1; i <= 10; i++) { shareDataOne.incr(); } }, "AA").start(); //-- new Thread(() -> { for (int i = 1; i <= 10; i++) { shareDataOne.decr(); } }, "BB").start(); //++ new Thread(() -> { for (int i = 1; i <= 10; i++) { shareDataOne.incr(); } }, "CC").start(); //-- new Thread(() -> { for (int i = 1; i <= 10; i++) { shareDataOne.decr(); } }, "DD").start(); } }
2.Lock锁实现
package com.jenne.mydemo; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class ShareDataOne { private int number = 0; private Lock lock = new ReentrantLock();//创建可重用锁 private Condition cd = lock.newCondition();//替换Object监测方法( wait, notify和 notifyAll)等 public void incr() throws InterruptedException { lock.lock(); try { //判断 while (number != 0) { cd.await(); } //干活 number++; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知 cd.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void decr() throws InterruptedException { lock.lock(); try { //判断 while (number != 1) { cd.await(); } //干活 number--; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知 cd.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } public class NotifyWaitDemo { public static void main(String[] args) { ShareDataOne shareDataOne = new ShareDataOne(); //++ new Thread(() -> { for (int i = 1; i <= 10; i++) { try { shareDataOne.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "AA").start(); //-- new Thread(() -> { for (int i = 1; i <= 10; i++) { try { shareDataOne.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "BB").start(); //++ new Thread(() -> { for (int i = 1; i <= 10; i++) { try { shareDataOne.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "CC").start(); //-- new Thread(() -> { for (int i = 1; i <= 10; i++) { try { shareDataOne.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "DD").start(); } }
3.注意:
在上面两种实现简单的线程通信时,判断是否操作都是用while循环。为什么我们不用if判断呢?使用if会造成虚假唤醒操作。在java多线程判断时,不能用if,程序出事出在了判断上面,突然有一添加的线程进到if了,突然中断了交出控制权,没有进行验证,而是直接走下去了,加了两次,甚至多次

浙公网安备 33010602011771号