【问题标题】:How to block current thread until user calls a specific method?如何在用户调用特定方法之前阻塞当前线程?
【发布时间】:2017-07-02 03:56:53
【问题描述】:

我需要阻塞当前线程,直到我调用以下两个方法之一(我创建的)。

  • onJobComplete()
  • onJobError(Throwable t)

这些方法将从不同的线程调用。

CountDownLatch(1) 可以做到这一点吗? (当这两种方法中的任何一种被调用时,我都会减少)。似乎我只能将CountDownLatchnew 线程一起使用。

如果没有,我该怎么做?

背景:https://github.com/ReactiveX/RxJava/issues/5094(我需要使下面的同步 onRun() 方法从 3rd 方库异步)

   /**
    * The actual method that should to the work.
    * It should finish w/o any exception. If it throws any exception,
    * {@link #shouldReRunOnThrowable(Throwable, int, int)} will be 
    * automatically called by this library, either to dismiss the job or re-run it.
    *
    * @throws Throwable Can throw and exception which will mark job run as failed
    */
    abstract public void onRun() throws Throwable;

更多信息:由于库限制,我无法控制onRun() 何时启动。库需要此方法是同步的,因为它的完成会自动向库发出“作业”成功完成的信号。我想“暂停”onRun() 并阻止它返回,启动我自己的异步线程,并在我的异步线程完成后“恢复”onRun()(允许onRun() 返回)。

【问题讨论】:

  • 我会让这两种方法设置一个布尔值并且运行休眠直到变量改变,或者wait/notify呢?
  • 那么,您的“当前线程”在做什么?问题可以更具体吗? wait/notify(或await/signal)似乎是你可以研究的。但是还有其他更好的并发构造,比如Future。你的问题太模糊了,人们无法提出建议
  • 当然,使用Future
  • @AdrianShum 当前线程是由第三方库控制的线程。这个库调用了一个特定的方法,在我决定异步调用 onJobComplete() 之前,我需要阻止它返回。如何有效地阻止方法返回,直到我想要它?
  • 所以,您的“当前”线程想要生成一个线程在后台执行某些操作,而“当前”线程需要等到该后台作业完成?那你为什么不直接使用FutureTask + 任何Executor 呢?你能举一个更具体的例子来说明你想要做什么吗?

标签: java multithreading concurrency java.util.concurrent


【解决方案1】:

使用锁和条件的示例。

class YourJob {
    boolean markFinished = false;   // is the job explicitly marked as finished
    final Lock lock = new ReentrantLock();
    final Condition finished = lock.newCondition();

    public void onRun() {
        // your main logic

        lock.lock();
        try {
            while(!markFinished) {
                finished.await();
            }
        } finally {
            lock.unlock();
        }
    }

    public void complete() {  // the name onComplete is misleading, as onXxx is usually
                              // used as method to be implemented in template method
        lock.lock();
        try {
            complete = true;
            finished.signalAll();
        } finally {
            lock.unlock();
        }
    }
}

如果您使用的是旧版本的 Java 或更喜欢使用 Object wait() 并通知,则类似:

class YourJob {
    boolean markFinished = false;   // is the job explicitly marked as finished

    public void onRun() {
        // your main logic

        synchronized (this) {
            while(!markFinished) {
                wait();
            }
        }
    }

    public synchronized void complete() { 
        complete = true;
        notifyAll();
    }
}

所以要使用它:

YourJob job  = new YourJob();
tellYourLibCallJobOnRun(job);   // job.onRun() invoked asynchronously

//..... doing something else
// if job.onRun() is invoked in background, it will be blocked waiting
// at the end

job.complete();   // job.onRun() will continue after this

【讨论】:

    猜你喜欢
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 2023-01-18
    • 2023-04-08
    • 2013-11-16
    • 1970-01-01
    相关资源
    最近更新 更多