Java:仅在线程处于等待状态时,如何才能通知该线程? [英] Java: How can I notify a thread only if it is waiting?

查看:106
本文介绍了Java:仅在线程处于等待状态时,如何才能通知该线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在第一个Java线程中,我有:

In a first Java thread I have:

while (!isDone) {
    try {
        synchronized (this) {
            wait();
        } 
    } catch (InterruptedException e) {
            e.printStackTrace();
    }
    doSomeVeryLongRunningTask();
}

在另一个线程中,我想发送一个通知信号:

In another thread, I want to send a notify signal:

synchronized (thr1) {
    thr1.notify();
}

但是,如果doSomeVeryLongRunningTask()方法正在运行,我不希望第二个线程被阻塞.我只想通知第一个线程正在等待,以便第二个线程可以继续执行任务而不会被锁定.

However, if the doSomeVeryLongRunningTask() method is running, I don't want the second thread to get blocked. I only want to notify the first thread if it is waiting so that the second thread can continue it tasks without getting locked.

我该如何修复上面的代码来完成此任务?

How might I fix the code above to accomplish this?

推荐答案

您要解决的问题不存在. synchronized块仅在另一个线程已在同一对象上同步 synchronized块内时,才会阻塞该线程.由于您的doSomeVeryLongRunningTask()将在synchronized块之外调用,因此如果另一个线程在doSomeVeryLongRunningTask()方法内部,则通知线程将永远不会被阻塞.

They problem you want to fix does not exist. synchronized blocks will block the thread only if another thread is already inside a synchronized block synchronizing on the same object. Since your doSomeVeryLongRunningTask() will be called outside the synchronized block the notifying thread will never get blocked if the other thread is inside the doSomeVeryLongRunningTask() method.

但这带来了另一个问题.您似乎在想,waitnotify调用始终是成对的.事实并非如此,您可以随意拨打notify,而无需任何人收听. wait调用也可能虚假"返回,也就是没有明显原因的情况.因此,您需要定义另一个硬条件",该条件由在synchronized块内修改和检查的状态定义.

But this raises another problem. You seem to be thinking, that wait and notify invocations are always paired. This is not the case, you may call notify as often as you wish without anyone listening to it. It might be also the case that a wait invocation returns "spuriously", i.e. for no apparent reason. You therefore need to define another "hard condition" which is defined by a state that is modified and checked inside the synchronized block.

例如在您的实例中具有thr1变量的类中,可以定义boolean标志:

E.g. inside the class whose instance you have in your thr1 variable, you can define a boolean flag:

boolean condition;

然后您修改等待方法,如下所示:

Then you modify you waiting method like this:

while(!isDone) {
  try {
    synchronized(this) {
      while(!condition) wait();
      if(isDone) break;// skip doSomeVeryLongRunningTask()
      condition=false;
    }
  } catch(InterruptedException e) {
    e.printStackTrace();
  }
  doSomeVeryLongRunningTask();
}

通知代码为:

synchronized(thr1) {
  thr1.condition=true;
  thr1.notify();
}

这样,您的通知代码仍不会被阻塞(至少在相当长的时间内不会阻塞),但是等待线程将等待至少一个通知在一个循环周期内发生.

This way your notifying code still won’t get blocked (at least never for a significant time) but the waiting thread will wait for at least one notification to happen within one loop cycle.

这篇关于Java:仅在线程处于等待状态时,如何才能通知该线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆