zoukankan      html  css  js  c++  java
  • JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法

    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();
            }
        }
    }
    

    结果同样是正确的

    然而 Condition 更强大的是精确通知和精确唤醒, 之前的运行结果线程之间是随机运行的,如果让线程 1,2,3,4 依次循环有序执行, 就要用到Condition

    public class JucPCdemo01 {
        public static void main(String[] args) {
            //JUC 版本的 就是来替代 synchronized版本的
            //4个线程依次循环有序执行, num 初始值为0, 线程1--A,  线程2--B,  线程3--C, 线程4--D
            DataC data = new DataC();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.printA();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"thread-1").start();
    
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.printB();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"thread-2").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.printC();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"thread-3").start();
    
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.printD();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"thread-4").start();
        }
    
    }
    
    class DataC{
        private Lock lock = new ReentrantLock();
        private Condition condition1 = lock.newCondition();//对应A
        private Condition condition2 = lock.newCondition();//对应B
        private Condition condition3 = lock.newCondition();//对应C
        private Condition condition4 = lock.newCondition();//对应D
    
        private String str = "A";
        public void printA() throws InterruptedException {
            //先加锁
            lock.lock();
            try {
                while(! "A".equals(str)){
                    condition1.await();//只要不是 A 就等待
                }
                System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
                str = "B";
                condition2.signal();//这里指定唤醒 线程2 对应B
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //释放锁
                lock.unlock();
            }
        }
    
        public void printB() throws InterruptedException {
            //先加锁
            lock.lock();
            try {
                while(!"B".equals(str)){
                    condition2.await();//只要不是B 就等待
                }
                System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
                str = "C";
                condition3.signal();//这里指定唤醒 线程3 对应C
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //释放锁
                lock.unlock();
            }
        }
    
        public void printC() throws InterruptedException {
            //先加锁
            lock.lock();
            try {
                while(! "C".equals(str)){
                    condition3.await();//只要不是C 就等待
                }
                System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
                str = "D";
                condition4.signal();//这里指定唤醒 线程4 对应D
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //释放锁
                lock.unlock();
            }
        }
    
        public void printD() throws InterruptedException {
            //先加锁
            lock.lock();
            try {
                while(! "D".equals(str)){
                    condition4.await();//只要不是D 就等待
                }
                System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
                str = "A";
                condition1.signal();//这里指定唤醒 线程1 对应A
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //释放锁
                lock.unlock();
            }
        }
    
    }
    

    运行结果为;

  • 相关阅读:
    606. Construct String from Binary Tree
    696. Count Binary Substrings
    POJ 3255 Roadblocks (次短路)
    POJ 2823 Sliding Window (单调队列)
    POJ 1704 Georgia and Bob (博弈)
    UVa 1663 Purifying Machine (二分匹配)
    UVa 10801 Lift Hopping (Dijkstra)
    POJ 3281 Dining (网络流之最大流)
    UVa 11100 The Trip, 2007 (题意+贪心)
    UVaLive 4254 Processor (二分+优先队列)
  • 原文地址:https://www.cnblogs.com/lvcai/p/13470950.html
Copyright © 2011-2022 走看看