gpt4 book ai didi

java - Java 中的信号条件变量触发等待

转载 作者:行者123 更新时间:2023-11-29 05:46:57 25 4
gpt4 key购买 nike

我创建了一个 Runnable 类,它定期执行一些任务。此类有一个方法可以触发任务的立即执行,无论指定的时间是否已经过去。

类确实在指定时间执行周期性任务,但触发没有按预期工作。
下面是带有 main 方法的简化类代码。根据我对 API 文档的解释,当 trigger 被调用时,await 发出信号并且它必须返回,以便或多或少地立即 无需等待指定时间。

Java 锁和条件有什么问题?我无法弄清楚为什么我的 trigger 方法没有按预期运行?

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.*;

public class PeriodicRunner implements Runnable {

private Lock lock = new ReentrantLock();
private Condition cond = lock.newCondition();

public void trigger() {
lock.lock();
try {
cond.signalAll();
}
finally {
lock.unlock();
}
}

@Override
public void run() {
lock.lock();
try {
while(true) {
cond.await(5, TimeUnit.SECONDS);
System.out.println("some task here");
}
}
catch(InterruptedException ex) {
}
finally {
lock.unlock();
}
}

public static void main(String[] args) throws InterruptedException {

PeriodicRunner pr = new PeriodicRunner();
new Thread(pr).start();
pr.trigger();
}
}

最佳答案

我认为使用 ScheduledExecutorService 可以更透明地实现您想要的:

class PeriodicRunner implements Runnable
{
private final ScheduledExecutorService _scheduler = Executors.newSingleThreadScheduledExecutor();

PeriodicRunner()
{
_scheduler.scheduleWithFixedDelay(this, 5, 5, TimeUnit.SECONDS);
}

public void trigger()
{
_scheduler.execute(this);
}

public void run()
{
System.out.println("some task here");
}
}

更新

例如,以下内容:

PeriodicRunner runner = new PeriodicRunner();
Thread.sleep(TimeUnit.SECONDS.toMillis(12));
System.out.println("[" + new Date() + "] triggering extra task");
runner.trigger();
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
System.out.println("[" + new Date() + "] triggering extra task");
runner.trigger();
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
System.out.println("[" + new Date() + "] triggering extra task");
runner.trigger();

将产生输出:

[Wed Mar 20 13:18:31 CST 2013] some task here
[Wed Mar 20 13:18:36 CST 2013] some task here
[Wed Mar 20 13:18:38 CST 2013] triggering extra task
[Wed Mar 20 13:18:38 CST 2013] some task here
[Wed Mar 20 13:18:39 CST 2013] triggering extra task
[Wed Mar 20 13:18:39 CST 2013] some task here
[Wed Mar 20 13:18:40 CST 2013] triggering extra task
[Wed Mar 20 13:18:40 CST 2013] some task here
[Wed Mar 20 13:18:41 CST 2013] some task here
[Wed Mar 20 13:18:46 CST 2013] some task here

更新 2

要扩展 d3rzKy 的答案,修复您现有的代码,您可以引入一个标志来指示 trigger 已被调用。此外,await 不能保证一直等待,因此您需要循环并跟踪您已经等待了多长时间。

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.*;

public class PeriodicRunner implements Runnable {

private final Lock lock = new ReentrantLock();
private final Condition cond = lock.newCondition();

private volatile boolean triggered = false;

public void trigger() {
lock.lock();
try {
triggered = true;
cond.signalAll();
}
finally {
lock.unlock();
}
}

@Override
public void run() {
lock.lock();
try {
while(true) {

if (!triggered) {
long remainingMs = TimeUnit.SECONDS.toMillis(5);
long dueTimeMs = System.currentTimeMillis() + remainingMs;
while (remainingMs > 0 && !triggered) {
if (cond.await(remainingMs, TimeUnit.MILLISECONDS)) {
break;
}
remainingMs = dueTimeMs - System.currentTimeMillis();
}
}
triggered = false;
System.out.println("some task here");
}
}
catch(InterruptedException ex) {
}
finally {
lock.unlock();
}
}

public static void main(String[] args) throws InterruptedException {

PeriodicRunner pr = new PeriodicRunner();
new Thread(pr).start();
pr.trigger();
}
}

关于java - Java 中的信号条件变量触发等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15515369/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com