java界面实时通知_Java中的等待/通知机制(wait/notify)

当一个线程修改了一个对象的值,另外一个线程需要感知到这个变化,并且做出相应的操作时,可以使用Java中的等待/通知机制去实现这个功能。

与等待/通知相关的方法是Java中所有对象都具备的方法,它们被定义在java.lang.Object中。

notify()方法:通知一个在对象上等待的线程,使其从wait()方法中返回,并且返回的前提是该线程获取到了对象的锁。

notifyAll()方法:与notify()不同的是,会通知所有等待在该对象上的线程。

wait()方法:调用该方法的线程会在对象上等待,进入WAITING状态,只有等待另外的线程通知或者被中断才会返回。调用wait()方法后,会释放对象的锁。

wait(long timeout):超时等待一段时间,如果等待指定时间后还没有收到通知就会超时返回,参数单位为毫秒。

wait(long timeout, int nanos):超时等待更加精确的实现方法,可精确到纳秒。

当线程A调用的对象O的wait()方法进入等待状态,而另一个线程B调用了对象O的notify()或者notifyAll()方法,线程A将会收到通知从O的wait()返回,继续执行后续操作。

等待/通知的经典实现方式:

等待方(消费者):

synchronized(obj){

while(判断条件不满足){

obj.wait();

}

其它处理逻辑

}

通知方(生产者):

synchronized(obj){

改变条件

obj.notifyAll();

}

使用等待/超时机制实现一个简单的对象池,模拟多个线程不断地从对象池中取出资源,使用完后归还资源到对象池中,使得其它线程可以继续使用这些资源。

定义资源类:

public class Resource {

private String name;

public Resource(String name) {

this.name = name;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

定义对象池:

public class ResourcePool {

// 使用双向列表保存所有的资源

private LinkedList pool = new LinkedList();

public ResourcePool(int poolSize) {

// 初始化pool,将可用的对象放入pool中

for (int i = 0; i 

pool.add(new Resource("RES_" + i));

}

}

// 获取资源

public Resource getResource(long timeout) {

long future = System.currentTimeMillis() + timeout;

long waitRemain = timeout;

synchronized (pool) {

// 判断有没有资源,若没有则等待

while (pool.isEmpty()) {

try {

// 在pool对象上等待,此时会释放pool对象的锁

pool.wait(waitRemain);

} catch (InterruptedException e) {

e.printStackTrace();

}

waitRemain = future - System.currentTimeMillis();

if (waitRemain <= 0) {

// 若等待超时,则返回null

System.out.println(Thread.currentThread().getName() + " get resource time out");

return null;

}

}

// 将资源从pool中移除,并返回资源

Resource resource = pool.removeFirst();

System.out.println(Thread.currentThread().getName() + " get resource: " + resource.getName());

return resource;

}

}

// 释放资源

public void releaseResource(Resource resource) {

if (resource != null) {

synchronized (pool) {

// 归还资源

pool.addLast(resource);

System.out.println(Thread.currentThread().getName() + " released resource: " + resource.getName());

// 通知所有等待在pool对象上的线程

pool.notifyAll();

}

}

}

}

main方法:

public static void main(String[] args) {

// 多个线程从资源池中同步获取资源

final ResourcePool resPool = new ResourcePool(5);

// 使用闭锁,让所有线程同时开始执行

final CountDownLatch startGate = new CountDownLatch(1);

for (int i = 0; i 

Thread thread = new Thread(new Runnable() {

public void run() {

try {

// 等待闭锁的计数器为0时,才能继续向下执行

startGate.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

// 获取资源,5秒超时

Resource resource = resPool.getResource(5000);

if (resource != null) {

try {

// 随机等待(1~10秒)若干秒后,再释放资源

Random random = new Random();

Thread.sleep((random.nextInt(9) + 1) * 1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

resPool.releaseResource(resource);

}

}

});

thread.setName("Th_" + i);

thread.start();

}

// 闭锁的计数减1,此时值为0,所有线程开始继续执行

startGate.countDown();

}

控制台输出:

Th_9 get resource: RES_0

Th_7 get resource: RES_1

Th_8 get resource: RES_2

Th_6 get resource: RES_3

Th_3 get resource: RES_4

Th_6 released resource: RES_3

Th_0 get resource: RES_3

Th_7 released resource: RES_1

Th_4 get resource: RES_1

Th_8 released resource: RES_2

Th_2 get resource: RES_2

Th_1 get resource time out

Th_5 get resource time out

Th_0 released resource: RES_3

Th_4 released resource: RES_1

Th_9 released resource: RES_0

Th_2 released resource: RES_2

Th_3 released resource: RES_4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值