您的位置:首页 > 编程语言 > Java开发

[JAVA]等待通知机制的2种实现

2017-12-28 22:28 477 查看
最近笔者在空闲之余,温习了下JAVA多线程编程。经常看,却经常忘记。可能是由于用的不多的缘故吧。这里针对多线程的等待通知的机制的2种实现进行总结。加深理解和认识。

等待通知机制

首先介绍下什么是等待通知机制。这里举一个生活的例子。

大家去餐馆吃饭的时候,会取号进行”等待“。等到号了,餐馆工作人员会”通知“你前去就餐。

这就是一个简单的等待通知的例子。好了,接下来介绍下它的2种实现。

wait()和notify()实现等待通知机制

源码见Github

去餐馆就餐的客人(等待者)

package com.zju.javastudy.waitnotify.demo1;

/**
* @author Arthur
* @Date 2017/12/28
* @Decription: 饿着的人,去餐馆取号,等待者
*/
public class HungryPeople implements Runnable {
/**
* 座位
*/
private Object seat;

public HungryPeople(Object seat) {
this.seat = seat;
}

@Override
public void run() {
synchronized (seat) {
try {
System.out.println("HungryPeople:去餐馆吃饭,先取号...");
seat.wait();//等待叫号
System.out.println("HungryPeople:到号,有位置了!可以吃饭了!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}


餐馆(通知者)

package com.zju.javastudy.waitnotify.demo1;

/**
* @author Arthur
* @Date 2017/12/28
* @Decription: 餐馆,通知者
*/
public class Restaurant implements Runnable {
/**
* 座位,实质就是锁
*/
private Object seat;

public Restaurant(Object o) {
this.seat = o;
}

@Override
public void run() {
try {
//模拟等待
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (seat) {
System.out.println("Restaurant:有空位,通知客人来就餐...");
seat.notify();//通知到号
System.out.println("Restaurant:完成通知");

}

}

}


测试

package com.zju.javastudy.waitnotidy.demo1;

import com.zju.javastudy.waitnotify.demo1.HungryPeople;
import com.zju.javastudy.waitnotify.demo1.Restaurant;
import org.junit.Test;

import static sun.jvm.hotspot.runtime.PerfMemory.start;

/**
* @author Arthur
* @Date 2017/12/28
* @Decription: 餐馆取号吃饭的测试例子
*/
public class WaitNotidyTest1 {

@Test
public void test() throws InterruptedException {
Object seat = new Object();//座位
Restaurant restaurant = new Restaurant(seat);
HungryPeople hungryPeople = new HungryPeople(seat);
Thread hungryPeopleThread = new Thread(hungryPeople);

hungryPeopleThread.start();
Thread restaurantThread = new Thread(restaurant);
restaurantThread.start();

//子线程结束后,再结束main线程
hungryPeopleThread.join();
restaurantThread.join();
}
}


结果



使用Condition实现部分通知

源码见Github

去餐馆就餐的客人(等待者)

package com.zju.javastudy.waitnotify.demo2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
* @author Arthur
* @Date 2017/12/28
* @Decription: 饿着的人,去餐馆取号,等待者
*/
public class HungryPeople implements Runnable {
/**
* 所有座位
*/
private ReentrantLock allSeat;

/**
* 等待的桌(大桌/小桌)
*/
private Condition seat;

public HungryPeople(ReentrantLock allSeat,Condition seat) {
this.allSeat = allSeat;
this.seat = seat;
}

@Override
public void run() {
allSeat.lock();
try {
seat.await();
System.out.println(Thread.currentThread().getName()+":等到位置");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
allSeat.unlock();
}

}
}


餐馆(通知者)

package com.zju.javastudy.waitnotify.demo2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
* @author Arthur
* @Date 2017/12/28
* @Decription: 餐馆,通知者
*/
public class Restaurant implements Runnable {

/**
* 所有座位
*/
private ReentrantLock allSeat;

/**
* 小桌
*/
private Condition smallSeat;

/**
* 大桌
*/
private Condition bigSeat;

public Restaurant(ReentrantLock allSeat,Condition smallSeat, Condition bigSeat) {
this.allSeat = allSeat;
this.smallSeat = smallSeat;
this.bigSeat = bigSeat;
}

@Override
public void run() {
//这里模拟通知大桌
try {
allSeat.lock();
Thread.sleep(2000);
System.out.println("Restaurant:有大桌空位,通知客人来就餐...");
bigSeat.signalAll();
System.out.println("Restaurant:完成大桌通知");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
allSeat.unlock();
}

//这里模拟通知小桌
try {
Thread.sleep(3000);
allSeat.lock();
System.out.println("Restaurant:有小桌空位,通知客人来就餐...");
smallSeat.signalAll();
System.out.println("Restaurant:完成小桌通知");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
allSeat.unlock();
}
}
}


测试

package com.zju.javastudy.waitnotidy.demo2;

import com.zju.javastudy.waitnotify.demo2.HungryPeople;
import com.zju.javastudy.waitnotify.demo2.Restaurant;
import org.junit.Test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
* @author Arthur
* @Date 2017/12/28
* @Decription: 餐馆取号吃饭的测试例子
*/
public class WaitNotidyTest2 {

@Test
public void test() throws InterruptedException {
ReentrantLock allSeat = new ReentrantLock();//座位
Condition smallSeat = allSeat.newCondition();//小桌
Condition bigSeat = allSeat.newCondition();//大桌

//实例化 餐馆,小桌客人和大桌客人
Restaurant restaurant = new Restaurant(allSeat,smallSeat,bigSeat);
HungryPeople hungryPeopleWaitSmall = new HungryPeople(allSeat,smallSeat);
HungryPeople hungryPeopleWaitBig = new HungryPeople(allSeat,bigSeat);

//小桌客人线程
Thread hungryPeopleWaitSmallThread = new Thread(hungryPeopleWaitSmall);
hungryPeopleWaitSmallThread.setName("smallSeatPeople");

//大桌客人线程
Thread hungryPeopleWaitBigThread = new Thread(hungryPeopleWaitBig);
hungryPeopleWaitBigThread.setName("bigSeatPeople");

//餐馆线程
Thread restaurantThread = new Thread(restaurant);

//开始模拟
hungryPeopleWaitSmallThread.start();
hungryPeopleWaitBigThread.start();
restaurantThread.start();

//子线程结束再结束main线程
hungryPeopleWaitSmallThread.join();
hungryPeopleWaitBigThread.join();
restaurantThread.join();
}
}


结果



这里通过2种实现,对等待通知进制进行了一个小结。例子可能不太恰当。欢迎批评指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: