首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程: java条件等待超时但无法返回

多线程: java条件等待超时但无法返回
EN

Stack Overflow用户
提问于 2016-06-11 14:22:11
回答 2查看 3.4K关注 0票数 3
代码语言:javascript
复制
Lock sharedLock = new ReentrantLock();
Condition condition = lock.newCondition();

主螺纹:

代码语言:javascript
复制
sharedLock.lock();
childThread.start();
condition.await(5, TimeUnit.SECONDS);
sharedLock.unlock();

子线程:

代码语言:javascript
复制
sharedLock.lock();
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
condition.signal();
sharedLock.unlock();

假设子线程发送网络请求并等待响应,我希望主线程等待最多5秒,如果超时,请重试请求。但是当await()超时时,它无法获得锁,因为子线程仍然持有锁,所以它仍然等待锁,直到子线程释放它,这需要10秒。

如何实现我的要求:主线程等待子线程的信号,但有一个有限度的超时?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-11 15:31:22

这不是你应该怎么做的,你应该:

  1. 创建一个ExecutorService (线程池),您应该检查类Executors的方法,以便在您的情况下选择最好的方法,但是Executors.newFixedThreadPool是一个很好的开始。
  2. 将任务作为FutureTask提交到线程池
  3. 然后用超时调用get
  4. 正确管理TimeoutException

以下是如何做到这一点:

代码语言:javascript
复制
// Total tries
int tries = 3;
// Current total of tries
int tryCount = 1;
do {
    // My fake task to execute asynchronously
    FutureTask<Void> task = new FutureTask<>(
        () -> {
            Thread.sleep(2000);
            return null;
        }
    );
    // Submit the task to the thread pool
    executor.submit(task);
    try {
        // Wait for a result during at most 1 second
        task.get(1, TimeUnit.SECONDS);
        // I could get the result so I break the loop
        break;
    } catch (TimeoutException e) {
        // The timeout has been reached
        if (tryCount++ == tries) {
            // Already tried the max allowed so we throw an exception
            throw new RuntimeException(
                String.format("Could execute the task after %d tries", tries),
                e
            );
        }
    }
} while (true);

如何实现我的要求:主线程等待子线程的信号,但有一个有限度的超时?

以下是如何实现您的需求:

主螺纹:

代码语言:javascript
复制
lock.lock();
try {
    childThread.start();
    condition.await(5, TimeUnit.SECONDS);
} finally {
    sharedLock.lock();
}

子线程:

代码语言:javascript
复制
try {
    //do something, may take a long time
    Thread.sleep(10);// sleep to simulate a long execution
} finally {
    // Here we notify the main thread that the task is complete whatever
    // the task failed or not
    lock.lock();
    try {
        condition.signal();
    } finally {
        lock.unlock();
    }
}

正如您所看到的那样,任务不能在关键部分内执行,我们只获取锁来通知主线程仅此而已。否则,如果在超时后在关键部分执行任务,则主线程仍然需要再次获取锁,而且由于锁实际上是子线程所拥有的,因此它需要等待任务的结束,这使得超时完全无用。

NB: I将sharedLock重命名为ReentrantLock是一种独占锁,而不是共享锁,如果需要共享锁,请检查类Semaphore以定义许可总量。

票数 1
EN

Stack Overflow用户

发布于 2018-05-23 19:06:49

问题中的有效混淆是因为"Thread.sleep(10)“是在锁块内完成的。当等待(长时间,TimeUnit单元)由于超时而返回时,它仍然需要锁。因此,正如在另一个答案中所建议的,长时间运行的任务不应该在锁中才能正常工作。但最好有适当的文件来强调这一事实。例如,如果我们等待(5,TimeUnit.SECONDS),即等待5秒,并且在调用后10秒锁可用,那么即使锁在返回的时刻可用,它仍然会返回false。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37764805

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档