JUC 併發程式設計--02,生產者和消費者 synchronized的寫法 , juc的寫法
阿新 • • 發佈:2020-08-10
synchronized的寫法
class PCdemo{ public static void main(String[] args) { //多個執行緒操作同一資源 Data data = new Data(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-1").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-2").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-3").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-4").start(); } } //這是一個資源類, class Data { private int num = 0; //加1 public synchronized void increment() throws InterruptedException { while(num != 0){ this.wait(); } num++; System.out.println("當前執行緒名字:" + Thread.currentThread().getName() + "加1 操作, num為" + num); this.notifyAll(); } //減1 public synchronized void decrement() throws InterruptedException { while(num == 0){ this.wait(); } num--; System.out.println("當前執行緒名字:" + Thread.currentThread().getName() + "減1 操作, num為" + num); this.notifyAll(); } }
結果:
這裡需要注意一個概念: 虛假喚醒,就是說執行緒被喚醒了, 但不會被通知 如果把資源類Data中的 increment, decrement方法中的while 換為: if, 那麼執行的時候, 二個執行緒的結果是正常的, 如果二個以上就會出錯,結果為
JUC 版本的 生產者和消費者問題
public class JucPCdemo { public static void main(String[] args) { //JUC 版本的 就是來替代 synchronized版本的 DataJ data = new DataJ(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-1").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-2").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-3").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"thread-4").start(); } } class DataJ{ private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); private int num = 0; //加1 public void increment() throws InterruptedException { //先加鎖 lock.lock(); try { while(num != 0){ condition.await();//這個替代 this.wait() } num++; System.out.println("當前執行緒名字:" + Thread.currentThread().getName() + "加1 操作, num為" + num); condition.signalAll();// 這個來替代 this.notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { //釋放鎖 lock.unlock(); } } //減1 public void decrement() throws InterruptedException { //先加鎖 lock.lock(); try { while(num == 0){ condition.await();//這個替代 this.wait(); } num--; System.out.println("當前執行緒名字:" + Thread.currentThread().getName() + "減1 操作, num為" + num); condition.signalAll();// 這個來替代 this.notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { //釋放鎖 lock.unlock(); } } }
結果同樣是正確的