纯Java:我怎么知道我的线程是否在睡觉?

ino*_*nor 2 java multithreading synchronized

我有一个做一些事情的线程.其中一个就是睡一段时间.正常睡眠后,它调用delayFinished()方法,但如果睡眠中断,则delayFinished()不应调用.我还需要一个中止睡眠的方法,可以被其他线程调用.

所以这是捕获我的意图的实现,但我认为它不会起作用:

public class MyThread extends Thread {
   private boolean sleeping=false;
   private Object sleepingControl=new Object();

   //... other unrelated stuff...

   private void delay() {
      try {
          synchronized(sleepingControl) {
             sleeping=true;         
             sleep(delay);
             sleeping=false;                        
             delayFinished();
          }
      } catch (InterruptedException e) {
          sleeping=false;
      }
    }
    public void abortDelay() {
          synchronized(sleepingControl) {
             if (sleeping)          
                interrupt();
          }
    }
 }
Run Code Online (Sandbox Code Playgroud)

如果delay()被调用,并且在它休眠时,abortDelay()由另一个线程(主用例)abortDelay()调用,则会挂起在synchronized语句上,因为调用者delay()拥有该监视器并且还没有放弃它.

另一方面,如果以这种方式实现延迟:

   private void delay() {
      synchronized(sleepingControl) {
         sleeping=true;         
      }
      try {              
             sleep(delay);
Run Code Online (Sandbox Code Playgroud)

它可能delay()被调用,完成同步块设置睡眠为真,但随后abortDelay()被调用,interrupt() 即使线程尚未开始睡眠它也会调用.

有人可以建议对这些尝试进行任何改进吗

Mik*_*e Q 6

您需要调查Object.wait()/ notify()而不是使用sleep().使用wait()一个关键的事情是它在释放对象的锁定时等待允许另一个线程获取锁并用notify()唤醒它.

例如

public class MyThread extends Thread {
   private boolean aborted = false;
   private final Object sleepingControl=new Object();

   //... other unrelated stuff...

   private void delay() {
      try {
          synchronized(sleepingControl) {
             sleepingControl.wait(delay);

             if (!aborted)
                 delayFinished();
          }
      } catch (InterruptedException e) {
      }
    }
    public void abortDelay() {
          synchronized(sleepingControl) {
             aborted = true;
             sleepingControl.notify();
          }
    }
 }
Run Code Online (Sandbox Code Playgroud)

这也不是全部故事,因为wait()有一个奇怪的实现怪癖,它可以虚假地唤醒.因此,您需要手动循环wait()调用,如果它返回检查以查看时间是否实际到期.

实际上我认为你可以通过java.util.concurrent类实现上述更简单.看看Lock课程.