gpt4 book ai didi

java - 等待/通知 vs sleep /中断 vs ReentrantLock.Condition

转载 作者:行者123 更新时间:2023-11-29 04:15:36 25 4
gpt4 key购买 nike

我正在编写一种“按类型搜索”机制 (android),它在后台线程中进行 sqlite 查询并将结果发回 UI 线程。理想情况下,线程应该等待/ sleep ,唤醒以执行任何接收到的 Runnable 对象并返回 sleep 。实现这一目标的最佳方式是什么?为什么?

基本上我想了解这 3 个选项之间的主要区别是什么,以及哪个最适合这个具体场景

  1. sleep /中断

    public class AsyncExecutorSleepInterrupt {
    private static Thread thread;
    private static Runnable runnable;

    static {
    thread = new Thread(() -> {
    while (true) {
    try {
    Thread.sleep(10000);
    } catch (InterruptedException e) {
    if (runnable != null) {
    runnable.run();
    runnable = null;
    }
    }
    }
    });
    thread.start();
    }

    public static void execute(Runnable runnable) {
    AsyncExecutorSleepInterrupt.runnable = runnable;
    thread.interrupt();
    }}
  2. 等待/通知

    public class AsyncExecutorWaitNotify {
    private static Thread thread;
    private static Runnable runnable;

    private static final Object monitor = new Object();

    static {
    thread = new Thread(() -> {
    while (true) {
    synchronized (monitor) {
    try {
    monitor.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    continue;
    }
    if (runnable != null) {
    runnable.run();
    runnable = null;
    }
    }
    }
    });
    thread.start();
    }

    public static void execute(Runnable runnable) {
    AsyncExecutorWaitNotify.runnable = runnable;
    synchronized (monitor) {
    monitor.notify();
    }
    }}
  3. 重入锁

    public class AsyncExecutorLockCondition {

    private static final ReentrantLock lock = new ReentrantLock();

    private static final Condition cond = lock.newCondition();

    private static Thread thread;

    private static Runnable runnable;

    static {
    thread = new Thread(() -> {
    while(true){
    try {
    lock.lock();
    cond.await();
    runnable.run();
    lock.unlock();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    });
    thread.start();
    }

    public static void execute(Runnable runnable) {
    AsyncExecutorLockCondition.runnable = runnable;
    lock.lock();
    cond.signal();
    lock.unlock();
    }}

最佳答案

就我个人而言,我有点不喜欢第一种方法,可能主要是因为中断。如果有人、某事以某种方式调用并中断该线程怎么办?您将运行一些任意代码,这可能不是最好的主意。此外,当您中断时,您实际上是在用异常链填充堆栈跟踪,这是抛出异常的最昂贵的部分。

但是假设你不关心第二点,而你完全控制了第一点;在我看来,这种方法可能没有任何问题。

现在这个例子中Conditionalwait/notify 之间的差别很小。我不知道内部细节以及哪个可能更快或更好,但一般来说 Conditional 是首选;主要是因为它更容易阅读,至少对我而言。此外,Conditional 可以一直从不同的 锁中获取,这与synchronized 不同。

其他优点是(此处无关):您可以创建多个条件,从而只唤醒您想要的线程;例如,与 notifyAll 不同。然后是具有到期时间的方法,例如 awaitUntil(Date)await(long, TimeUnit)awaitNanos。甚至还有一种方法可以await 并完全忽略interrupts:awaitUninterruptibly

据说在 await 之后你不需要 lock::unlock 因为文档在这方面非常清楚:

The lock associated with this Condition is atomically released ...

一个更直接的方法是:

static class AsyncExecutor {

private static final ExecutorService service = Executors.newSingleThreadExecutor();

public static void execute(Runnable runnable) {
service.execute(runnable);
}
}

关于java - 等待/通知 vs sleep /中断 vs ReentrantLock.Condition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52555846/

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