-5

I need to block the current thread until I call one of two following methods (which I created).

  • onJobComplete()
  • onJobError(Throwable t)

These methods will be called from a different thread.

Is this possible with a CountDownLatch(1)? (which I would decrement when either of those two methods are called). Seems I can only use CountDownLatch with a new thread.

If not, how can I accomplish this?

background: https://github.com/ReactiveX/RxJava/issues/5094 (I need to make the below synchronous onRun() method from a 3rd party library asynchronous)

   /**
    * 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;

More info: Because of library limitations, I cannot control when onRun() starts. The library needs this method to be synchronous, because its completion automatically signals to the library that the "job" successfully completed. I want to "pause" onRun() and prevent it from returning, kick off my own asynchronous thread(s), and "resume" onRun() (allow onRun() to return) once my asynchronous thread completes.

ZakTaccardi
  • 12,212
  • 15
  • 59
  • 107
  • I would have these two method setting a boolean value and the run sleeping until the variable changes, or what about `wait/notify` ? – Scary Wombat Feb 14 '17 at 01:35
  • 1
    so, what is your "current thread" doing? Can the question be more specific? `wait`/`notify` (or `await`/`signal`) seems something you may look into. But there are also other better concurrency constructs, like `Future`. Your question is just too vague for people to suggest – Adrian Shum Feb 14 '17 at 01:51
  • Definitely, use `Future`. – dimo414 Feb 14 '17 at 03:49
  • @AdrianShum current thread is a thread controlled by a third party library. This library calls a specific method that I need to prevent from returning until I decide to asynchronously call `onJobComplete()` . How do I efficiently block a method from returning until I want it to? – ZakTaccardi Feb 14 '17 at 03:49
  • so, your "current" thread want to spawn a thread to do something in background, and the "current" thread need to wait until that background job is done? Why don't you just use a `FutureTask` + whatever `Executor` then? Can you make a more specific example to show what you are trying to do? – Adrian Shum Feb 14 '17 at 03:58
  • @AdrianShum Because of library limitations, I cannot control when `onRun()` starts. The library needs this method to be synchronous, because its completion automatically signals to the library that the "job" successfully completed. I want to "pause" the `onRun` method (prevent it from returning), kick off my own asynchronous thread(s), and "resume" the `onRun` method (allow `onRun` to return) once my asynchronous thread completes. – ZakTaccardi Feb 15 '17 at 16:26
  • @ScaryWombat isn't a while loop on a boolean very inefficient? – ZakTaccardi Feb 15 '17 at 16:28
  • @ZakTaccardi Your terminology is misleading. We use "Current Thread" normally describe the thread that current piece of code is running on. But here you means another background thread. Is my interpretation on what you want to do correct: You have a background thread that will execute your `Job`'s `onRun()` in unknown time (like by scheduling/timer etc). What you want to do is, when the job is started, you want something at the end of `onRun()` that will block it from finishing, until some other thread call `Job`'s `complete()/fail()` method. – Adrian Shum Feb 16 '17 at 01:52
  • @AdrianShum the current thread is the background thread that `onRun` is called on. I want to block that thread from within the `onRun` method – ZakTaccardi Feb 21 '17 at 01:14
  • @ZakTaccardi That's what I said: usually we use the term "Current Thread" as some other meaning. And I have already given an answer. – Adrian Shum Feb 21 '17 at 01:36

1 Answers1

0

Example of using Lock and Condition.

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();
        }
    }
}

Similar if you are using older version of Java or prefer using Object wait() and notify:

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();
    }
}

So to use it:

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
Adrian Shum
  • 38,812
  • 10
  • 83
  • 131