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(); } }
运行结果: