zoukankan      html  css  js  c++  java
  • Condition 的使用

    Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。Condition的使用必须是在lock修饰的语句块中。
    下面给出一个简单的示例:

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * Created by litao on 15/5/26.
     */
    public class TaskTest {
    
        private boolean flag;
        private int num;
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
    
        public void sub() {
            lock.lock();
            while (flag == false) {
                try {
                    condition.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 5; i++) {
                num--;
                System.out.println("sub num:" + num);
            }
            flag = false;
            condition.signal();
            lock.unlock();
        }
    
        public void add() {
            lock.lock();
            while (flag == true) {
                try {
                    condition.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 5; i++) {
                num++;
                System.out.println("add num:" + num);
            }
            flag = true;
            condition.signal();
            lock.unlock();
        }
    
        public static void main(String[] args) {
    
            final TaskTest taskTest = new TaskTest();
            Thread thread1 = new Thread() {
                @Override
                public void run() {
                    taskTest.sub();
                }
            };
            Thread thread2 = new Thread() {
                @Override
                public void run() {
                    taskTest.add();
                }
            };
            thread1.start();
            thread2.start();
        }
    }
    

    执行结果:
    add num:1
    add num:2
    add num:3
    add num:4
    add num:5
    sub num:4
    sub num:3
    sub num:2
    sub num:1
    sub num:0
    可以看出,condition.signal()和condition.await()在这种情况下和传统的notify,wait具有相同的功效。

    既然condition提供的功能和传统的方法相同,那为啥还要有这个东东呢?下面介绍condition的独特的地方。

    public class Buffer {
        private Lock lock = new ReentrantLock();
        private Condition readCondition = lock.newCondition();
        private Condition writeCondition = lock.newCondition();
        private LinkedList<String> buffers;
        private int size = 0;
        private int maxSize;
    
        public Buffer(int maxSize) {
            this.maxSize = maxSize;
            buffers=new LinkedList<String>();
        }
    
        public String get() {
            lock.lock();
            while (size == 0) {
                try {
                    readCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            String tmp = buffers.poll();
            size = size - 1;
            System.out.println(Thread.currentThread().getName()+" ,get: "+tmp);
            writeCondition.signalAll();
            lock.unlock();
            return tmp;
        }
    
        public void set(String str) {
            lock.lock();
            while (size == maxSize) {
                try {
                    writeCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            buffers.offer(str);
            size = size + 1;
            System.out.println(Thread.currentThread().getName()+" ,set: "+str);
            readCondition.signalAll();
            lock.unlock();
        }
    }
    

    上面代码使一个使用了Condition实现的的Buffer。
    这里将写和读分别使用了writeCondition和readCondition,相较于传统的notify,主要的区别是:使用condition可以按条件唤醒不同的线程,当可读的时候只唤醒读线程,当可写的时候只唤醒写线程。这样,不会致使某个无关的线程被唤醒后,立即又被阻塞。可以提高程序的执行效率。
    使用上面Buffer,实现的一个生产者-消费者模型

    import java.util.Random;
    
    /**
     * Created by litao on 15/5/26.
     * 生产者-消费者模型
     */
    public class ProducerAndConsumer {
    
        public static void main(String[] args) {
    
            final String[] randomStr = {
                    "0asaswwdwdwdw",
                    "1aswswswdwdwdw",
                    "2asasaswwdwd",
                    "3asaswwdwd",
                    "4sdsdwwdwd"
            };
            final Buffer buffer = new Buffer(5);
    
            final Producer producer = new Producer(buffer);
            final Consumer consumer = new Consumer(buffer);
            final Random random = new Random();
            for (int i = 0; i < 10; i++) {
                Thread thread1 = new Thread("producer" + i) {
                    @Override
                    public void run() {
                        int index = random.nextInt(5);
                        producer.produce(randomStr[index]);
                    }
                };
                thread1.start();
            }
    
            for (int i = 0; i < 10; i++) {
                Thread thread = new Thread("consumer" + i) {
                    @Override
                    public void run() {
                        String str = consumer.consum();
                        System.out.println("str:" + str);
                    }
                };
                thread.start();
            }
    
        }
        public static class Producer {
            private Buffer buffer;
    
            public Producer(Buffer buffer) {
                this.buffer = buffer;
            }
    
            public void produce(String str) {
                buffer.set(str);
            }
        }
    
        public static class Consumer {
            private Buffer buffer;
    
            public Consumer(Buffer buffer) {
                this.buffer = buffer;
            }
    
            public String consum() {
                return buffer.get();
            }
        }
    }
    

    程序执行结果:
    producer0 ,set: 0asaswwdwdwdw
    producer1 ,set: 0asaswwdwdwdw
    producer2 ,set: 0asaswwdwdwdw
    producer3 ,set: 3asaswwdwd
    producer4 ,set: 2asasaswwdwd
    consumer0 ,get: 0asaswwdwdwdw
    producer5 ,set: 4sdsdwwdwd
    str:0asaswwdwdwdw
    consumer1 ,get: 0asaswwdwdwdw
    str:0asaswwdwdwdw
    producer6 ,set: 0asaswwdwdwdw
    consumer4 ,get: 0asaswwdwdwdw
    str:0asaswwdwdwdw
    producer8 ,set: 1aswswswdwdwdw
    consumer5 ,get: 3asaswwdwd
    str:3asaswwdwd
    producer9 ,set: 4sdsdwwdwd
    consumer2 ,get: 2asasaswwdwd
    str:2asasaswwdwd
    consumer3 ,get: 4sdsdwwdwd
    str:4sdsdwwdwd
    producer7 ,set: 0asaswwdwdwdw
    consumer6 ,get: 0asaswwdwdwdw
    str:0asaswwdwdwdw
    consumer7 ,get: 1aswswswdwdwdw
    str:1aswswswdwdwdw
    consumer8 ,get: 4sdsdwwdwd
    str:4sdsdwwdwd
    consumer9 ,get: 0asaswwdwdwdw
    str:0asaswwdwdwdw

  • 相关阅读:
    VS-Visual Studio-IIS Express 支持局域网访问
    JAVA和C# 3DES加密解密
    Js调用Java方法并互相传参
    Cannot find SS.INI file for user *** 解决方法
    $.ajax()方法参数详解
    HANA Studio打开系统显示Secure storage is locked
    C#通过ODBC查询HANA数据库数据
    IIS7发布asp.net mvc提示404.0
    CentOS 搭建git服务
    解决用navicat远程连接数据库出现1045 access denied for user 'root'@'localhost' using password yes
  • 原文地址:https://www.cnblogs.com/limingluzhu/p/4870891.html
Copyright © 2011-2022 走看看