• 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会自动释放锁。

  • 相关阅读:
    随手感言
    unity序列化
    unity EditorGUILayer绘制报错
    Json文件的BOM
    unity StrangeIoc
    软件工程实践2017——实践总结
    个人作业——软件产品案例分析
    Gitkraken的使用
    软件工程实践2017——个人技术博客
    UGUI中显示粒子特效
  • 原文地址:https://www.cnblogs.com/hanease/p/15721279.html
Copyright © 2020-2023  润新知