简体   繁体   中英

Java: How to wake thread on demand?

Let's say I want to create an object that basically runs a thread infinitely. I want the thread to sleep while there is no need for him, but when there is a need for certain job to be done, it wakes the thread - gets the job done and goes back to sleep. I also want the jobs to be queued and be executed in the order they arrive. In cocoa/objective c there is an NSOperationQueue for that. I wonder if java has something similar.

What do you think?

I think a combination of a BlockingQueue and a ThreadPoolExecutor will do what you need.

Or, if you deploy on a Java EE app server, you could use JMS and a message-driven bean.

I would use an ExecutorService like

private final ExecutorService executor = Executors.newSingleThreadExecutor();

public void task(final int arg) {
    executor.execute(new Runnable() {
        @Override
        public void run() {
            // perform task using `arg`
        }
    });
}

This has a built in thread which wakes when a tasks is added and sleeps when there is no tasks left, a Blocking Queue for queue tasks.

You can use some BlockingQueue .

When you read from the queue (in the thread), you either get the next item, or if it is empty - wait until one is received.

This you are not actually sleeping the thread, but using the queue's blocking property. For example:

private BlockingQueue queue;
@Override
public void run() {
    while(true) {
        handle(queue.poll());
    }
}

The above code is in a Runnable - you can use an ExecutorService to start a runnable, or the old-fashioned way with a Thread

The queue of course is set externally, and is filled (again externally) with the incoming items.

You can find what you need in the java.util.concurrent library - it's a higher level API than Thread . Have a look at http://www.ibm.com/developerworks/java/library/j-jtp1126/index.html

Since you want something similar to the NSOperationQueue, I second going with Java's ExecutorService. I am not sure if ExecutorService polls or waits for an interrupt. If you need more control there are lower-level interrupt-driven approaches, along these lines:

class InterruptDriven {
   private final ReentrantLock lock = new ReentrantLock(true);
   private final Condition asynchronousTrigger = lock.newCondition();
   private AtomicBoolean poisoned = new AtomicBoolean(false);

   public void interrupt() {
      final ReentrantLock lock = this.lock;
      try {
         lock.lockInterruptibly();
         asynchronousTrigger.signal();
      } catch (InterruptedException ex) {
         ....
      } finally {
         lock.unlock();
      }
   }
   public void workerWait(){
      final ReentrantLock lock = this.lock;
      lock.lockInterruptibly();
      try {
         try {
            if (!poisoned.get()) {
               asynchronousTrigger.await();
               ... do some work here ...
            }
         } catch (InterruptedException ie) {
            ...
         }
      } finally {
         lock.unlock();
      }
   }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM