zoukankan      html  css  js  c++  java
  • java基础知识回顾之java Thread类学习(三)java多线程通信等待唤醒机制(wait和notify,notifyAll)

    1.wait和notify,notifyAll

    • wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以可以被任意对象调用的方法,定义在Object基类中。
    • wait()方法:对此对象调用wait方法导致本线程放弃对象锁,让线程处于冻结状态,进入等待线程的线程池当中。wait是指已经进入同步锁的线程,让自己暂时让出同步锁,以便使其他正在等待此锁的线程可以进入同步锁并运行,只有其它线程调用notify方法或者notifyAll方法后,才能唤醒线程池中等待的线程。
    • notify()方法:唤醒线程池中的任意一个线程。
    • notifyAll方法:唤醒线程池中的所有线程。

    2.线程间通信:多个线程操作同一个资源,但是操作的动作不同,任务不同。

    3.等待唤醒机制:操作共享数据的不同动作,一个存入,一个取出;当输入一个的时候,另一个要取出。先让输入线程等待,等输出线程取出后,再唤醒输入线程。

    下面看一个例子:需求是要求两个线程操作Resource资源类中的成员变量name,sex,要求一个线程往共享资源类中存入一个姓名和一个姓别,即存入一个资源对象,另一个线程就取出资源类中的对象。即存入一个,就要取出,资源类中对象为空的时候,就再存入一个。这个例子可以用等待唤醒机制解决。

    思路:这里在线程代码里面设计一个姓名为peter,性别为man;另一个姓名为“李明”,性别为“男”。通过模2进行切换。输入线程选择操作这连个对象。

    java基础知识回顾之java Thread类学习(八)--java.util.concurrent.locks(JDK1.5)与synchronized异同讲解

     

    看API文档介绍几个方法:

     JDK1.5中提供了多线程的升级解决方案:

               特点: 1.将同步synchronized显示的替换成Lock
                        2.接口Condition:Condition替代了Object监视器方法(wait、notify、notifyAll),分别替换成了await(),signal() (唤醒一个等待线                   程),signalAll() 唤醒多个线程。一个锁可以绑定多个condition对象,可以对应好几组wait,notify,notifyAll动作。

    java.util.concurrent.locks接口
     *     Lock接口下面的方法
     *     void lock():获取锁,如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。
     *     boolean tryLock():如果获得了锁,返回true。如果别的线程正在持有锁,返回false
     *     boolean tryLock(long time,//等待多长时间获得锁
                    TimeUnit unit)
                    throws InterruptedException:
           如果获取到锁,立即返回true,如果别的线程正在持有锁,会等待参数给定的时间,如果在这段时间内获得了锁就返回true,如果等待超时,返  回false。

    locks的实现类:
          java.lang.Object
                 -->java.util.concurrent.locks.ReentrantLock类一个可重入的互斥锁 Lock,替代synchronized,比synchronized有更强大的功能
                 -->Java.util.concurrent.locks.ReadWriteLock 提供了一对可供读写并发的锁。
                        

     使用新的锁完成生产者消费者模型:

    代码如下:

    仓库类(资源)

    复制代码
    class ResourceNew{
        private String name;
        private boolean flag = false;
        private int count=1;
        
        private final Lock lock = new ReentrantLock();//将同步synchronized显示的替换成Lock
        private Condition condition_cusumer = lock.newCondition();//同一个锁上可以绑定多个相关的Condition
        private Condition conditon_producer = lock.newCondition();
        
        public  void set(String name) throws InterruptedException{
            try{
                lock.lock();//显示的
                while(flag){
                    conditon_producer.await();//生产者等待t1,t2
                }
                this.name = name+"---"+count++;
                System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
                this.flag = true;
    //condition.signalAll();//唤醒本方和唤醒对方
                condition_cusumer.signal();//唤醒某个消费者
            }finally{
                lock.unlock();//每个线程进入锁必须要执行的操作,最终要释放锁
            }
        }
        
        public  void out() throws InterruptedException{
            try{
                lock.lock();
                while(!flag){
                    condition_cusumer.await();//消费者等待
                }
                System.out.println(Thread.currentThread().getName()+".消费者."+this.name);
                this.flag = false;
                conditon_producer.signalAll();//唤醒生产者
            }finally{
                lock.unlock();
            }
        }
        
    }
    复制代码

    生产者:

    复制代码
    /**
     * 
     * @author Administrator
     * 生产者负责生产,操作同一个资源,但是是生产动作
     *
     */
    class producerNew implements Runnable{
        private ResourceNew res;
        public producerNew(ResourceNew res){
            this.res = res;
        }
        public void run() {
            while(true){
                try {
                    res.set("..商品..");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    复制代码
    复制代码
    /**
     * 
     * @author Administrator
     * 消费者负责消费生产者提供的产品,操作的同一个资源,但是是消费动作
     *
     */
    class CusumerNew implements Runnable{
        private ResourceNew res;
        public CusumerNew(ResourceNew res){
            this.res = res;
        }
        public void run() {
            while(true){
                try {
                    res.out();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    复制代码

    消费者:

    复制代码
    /**
     * 
     * @author Administrator
     * 消费者负责消费生产者提供的产品,操作的同一个资源,但是是消费动作
     *
     */
    class CusumerNew implements Runnable{
        private ResourceNew res;
        public CusumerNew(ResourceNew res){
            this.res = res;
        }
        public void run() {
            while(true){
                try {
                    res.out();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    复制代码

     synchronized和java.util.concurrent.locks.Lock的异同 :
     * 相同点:Lock能完成synchronized所实现的所有功能。
     * 不同点:1.Lock比Synchonized更精确的线程锁语义和更好的性能。(Synchonized是独占锁,性能不高,而Lock是借助于JNI,性能更高)
     *            2.Lock必须手动释放锁,在finally里面调用unlock()方法释放锁,而synchronized会自动释放锁。

  • 相关阅读:
    LeetCode 515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 1022. 从根到叶的二进制数之和(Sum of Root To Leaf Binary Numbers)
    LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)
    LeetCode 617. 合并二叉树(Merge Two Binary Trees)
    LeetCode 206. 反转链表(Reverse Linked List) 16
    LeetCode 104. 二叉树的最大深度(Maximum Depth of Binary Tree)
    LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15
    LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14
  • 原文地址:https://www.cnblogs.com/hanease/p/15721279.html
Copyright © 2011-2022 走看看