zoukankan      html  css  js  c++  java
  • Lock接口与等待唤醒机制

    一  Lock接口

    Lock接口中常用的方法:

    我们使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Ticket类进行如下代码修改:

    package com.oracle.demo01;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Myticket4 implements Runnable {
        private int ticket=100;
        //创建Lock接口实现类对象
        private Lock lock=new ReentrantLock();
        public void run() {
            while(true){
                //获取锁
                lock.lock();
                if(ticket>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"出售第"+ticket--+"张票");
                }
                //释放锁
                lock.unlock();
            }
        }
        
    }

    二  等待唤醒机制

    在开始讲解等待唤醒机制之前,有必要搞清一个概念——线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制。

    等待唤醒机制所涉及到的方法:

     wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。

      notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。

      notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

    模拟资源类:

    package com.oracle.demo03;
    
    public class Resource {
        //共享资源
        public String name;
        public int age;
        //添加标记:true,赋值完成,false,输出完成
        public boolean flag=false;//先赋值在输出
    }

    输入线程类:

    public class Input implements Runnable {
        //对Resource进行赋值
        private Resource r;
        public Input(){}
        public Input(Resource r){
            this.r=r;
        }
        public void run() {
            int i=0;
            while(true){
                //添加同步代码块
                synchronized (r) {
                    //判断标记
                    if(r.flag){
                        try {
                            r.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if(i%2==0){
                        r.name="张三";
                        r.age=18;
                    }else{
                        r.name="李四";
                        r.age=81;
                    }
                    r.flag=true;
                    r.notify();
                }    
                i++;
            }
        }
    
    }

    输出线程类:

    public class Output implements Runnable {
        private Resource r;
        public Output(){}
        public Output(Resource r){
            this.r=r;
        }
        public void run() {
            
            //对Resource进行输出
            while(true){
            
                //添加同步锁
                synchronized (r) {
                    //判断标记
                    if(!r.flag){
                        try {
                            r.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(r.name+"..."+r.age);
                    //改标记,唤醒input
                    r.flag=false;
                    r.notify();
                }
            
            }
        }
        
    }

    测试类:

    public class Demo01 {
        public static void main(String[] args) {
            Resource r=new Resource();
            //创建线程任务
            Input in=new Input(r);
            Output out=new Output(r);
            Thread tin=new Thread(in);
            Thread tout=new Thread(out);
            tin.start();
            tout.start();
        }
    }

    运行结果:

     

  • 相关阅读:
    (转)sql server 生成树形菜单
    在Sublime Text 3中配置Python3的开发环境/Build System
    按回车键提交表单 问题
    多页面 返回 到同一页面
    sql 查找出表里所有字段
    sql 创建表变量,临时表
    sql语句中数据类型转换函数:CAST 和 Convert
    sql isnull函数
    判断值是否为整数
    TSQL游标使用
  • 原文地址:https://www.cnblogs.com/zzq123/p/10248757.html
Copyright © 2011-2022 走看看