Java:Object.wait(long)已损坏

时间:2017-06-15 19:58:35

标签: java multithreading wait

在我看来,好像Object.wait的超时版本很少可以原样使用。这是因为:

  • 该方法无法处理虚假唤醒。
  • 该方法不会发出由于通知或超时而返回的信号。

带有谓词作为参数的C++ version似乎使其正确。 Object中带有签名的相应Java方法

boolean wait(long timeOutMillis, BooleanSupplier condition)

可以方便地使用如下:

Object obj = ...;
BooleanSupplier condition = ...;
synchronized (obj) {
    if (obj.wait(1000, condition)) {
        // condition is fulfilled
    } else {
        // timeout happened
    }
}

作为一种解决方法,我可以使用以下丑陋的帮助方法:

public static boolean safeWait(Object waitObject, long timeOutMillis, BooleanSupplier condition) throws InterruptedException {
    if (condition.getAsBoolean()) {
        return true;
    }
    long rest = timeOutMillis;
    while (true) {
        long t0 = System.currentTimeMillis();
        waitObject.wait(rest);
        long t1 = System.currentTimeMillis();
        long waited = t1 - t0;
        if (condition.getAsBoolean()) {
            return true;
        }
        rest = rest - waited;
        if (rest <= 0) {
            return false;
        }
    }
}

我最好提出一些问题:

  • 我是对的,它已经坏了吗?
  • 他们为什么不解决这个问题?
  • 有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:1)

你的safeWait(...)原则上看起来不错,但你可以简化一下: public static boolean safeWait(Object waitObject,long timeOutMillis,BooleanSupplier condition)     抛出InterruptedException {     long now = System.currentTimeMillis();     long end_time = now + timeOutMillis;     while(!condition.getAsBoolean()){         if(now&gt; end_time){             返回false;         }         waitObject.wait(end_time - now);         now = System.currentTimeMillis();     }     返回true; }

答案 1 :(得分:1)

Object.wait()有一些限制,这就是Java引入Lock的原因。并且通过使用“trylock()”方法,如果其他线程已经获取了锁,则代码不会阻塞。

见下文:

    Boolean workDone = false;
    while (!workDone) {
        Lock lock = new ReentrantLock();
        Boolean lockAcquired = false;
        try {
            lockAcquired = lock.tryLock(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {  // this exception will be thrown if current thread is interrupted while acquiring the lock or has its interrupted status set on entry to "tryLock" method.
            Thread.currentThread().interrupt();  // this thread's interrupt status will be set to "true" (this is needed because the current thread's interrupted status was cleared by InterruptedException)
            System.out.println(Thread.currentThread().isInterrupted());  // true
        }
        if (Thread.currentThread().isInterrupted()) {
            // close resources. finish as quick as possible
        }
        if (lockAcquired) {
            // you have the lock. you can execute the critical section of the code (read/modify mutable shared state)
            lock.unlock();  // remember to release the lock at the end of your critical section.
            workDone = true;
        }
    }