How can I create an "event-driven" background thread in Java?
Asked Answered
C

2

5

I like the simplicity of invokeLater() for sending units of work to the AWT EDT. It would be nice to have a similar mechanism for sending work requests to a background thread (such as SwingWorker) but as I understand it, these do not have any sort of event queueing & dispatch mechanism, which is what invokeLater() depends upon.

So instead, I've ended up giving my background thread a blocking queue, to which other threads send messages, and the thread essentially runs a receive loop, blocking until a message arrives.

That, in fact, might be exactly how one would implement EDT-like behavior in a background thread (or would it?). On the other hand, I like the simplicity of a thread that simply dangles there inertly, processing "work droplets" whenever they happen to be dispatched to it from some unseen Event Dispatching Queue in the sky. Does Java provide a way to create such an "event-driven worker thread"? Or is message-queueing the right way to do this, after all? And in a related vein, are there drawbacks to the invokeLater() technique of message-passing?

Chromatin answered 12/8, 2011 at 18:31 Comment(0)
W
1

You should take a look at java.util.concurrent, more specifically at Executor's, which are usually just a thread pool that can process a request like this: executor.execute(runnableTask);. If you want a single thread to process all the request, then create your thread with a single thread: executor = Executors.newSingleThreadExecutor()'. There are also ExecutorService's which can return a value when the task is done.

Whoreson answered 12/8, 2011 at 18:38 Comment(4)
Good to know about, but doesn't seem to provide the "dispatching" I was looking for.Chromatin
Sending a runnable on a single threaded executor is exactly like sending a runnable on the EDT. The tasks get queued up for processing and the thread stays alive waiting if there are no current jobs.Whoreson
@Chromatin I was reading the description of your problem in the comments of the other answer and it seems that a single thread executor is exactly what you are looking for.Whoreson
It works great. Executors is a gold mine. Thank you for pointing it out.Chromatin
F
3

The Producer-Consumer Design Patter (which is what you're employing with your blocking queue) is just a different approach to solving a different class of problems; EDT employs the Worker Design Pattern. Take a look at both design patterns and see which one suits your needs best.

  • The Producer-Consumer pattern is generally used when you have multiple threads executing independent tasks separately.
  • The Worker pattern, employed by the EDT, is used to funnel the result of multiple tasks into a single thread (in this case the GUI thread).

Of course, you can take the Producer-Consumer pattern and achieve similar behavior to the Worker pattern if you have a single queue and a single consumer with multiple producers, but that just highlights the flexibility of design patterns. So the point, again, is that choosing a design pattern is based on what works best for your particular situation- there is no particularly wrong choice when the patterns are flexible enough to accommodate the behavior you desire.

Faina answered 12/8, 2011 at 18:40 Comment(5)
My situation definitely calls for Worker pattern - I need each task to be processed serially, by a single thread. However, you linked to SwingWorker - I may be missing the point, but isn't it possible for multiple SwingWorker threads to be spawned simultaneously? That wouldn't work for me.Chromatin
A SwingWorker employs the worker design pattern (which is what is depicted in the wiki page) in order to prevent the GUI from freezing when you have multiple tasks. The updates to the GUI are still done from the GUI thread tho, because the SwingWorker calls back when it's done with its operation. Based on your comment, this doesn't seem like the right approach for you. If your operation requires that it's done on a single thread, then employ the Producer-Consumer pattern with a single consumer (thread) and multiple producers- let only the consumer execute the task.Faina
@Chap, one more thing: are you trying to prevent a single task from being executed by multiple threads or are you trying to prevent multiple tasks from being executed simultaneously (on multiple threads)? My previous comment may be wrong depending on what you meant by "I need each task to be processed serially, by a single thread."Faina
I'm trying to force a single method ("getRecordAndBufferNext") to be run on a single thread - so that, if another request for that method occurs before the first has finished, it will be queued up behind the first, rather than being sent to another thread and racing with the first. I don't know if that answers your question ....? I know I've got to get the work off the GUI thread; I just want to ensure that the work requests ("fetch next record from data set") are performed one after the other, not concurrently.Chromatin
@Chap, that answers my question, so no changes to my previous comments: just use a single consumer with multiple producers (if you even need producers).Faina
W
1

You should take a look at java.util.concurrent, more specifically at Executor's, which are usually just a thread pool that can process a request like this: executor.execute(runnableTask);. If you want a single thread to process all the request, then create your thread with a single thread: executor = Executors.newSingleThreadExecutor()'. There are also ExecutorService's which can return a value when the task is done.

Whoreson answered 12/8, 2011 at 18:38 Comment(4)
Good to know about, but doesn't seem to provide the "dispatching" I was looking for.Chromatin
Sending a runnable on a single threaded executor is exactly like sending a runnable on the EDT. The tasks get queued up for processing and the thread stays alive waiting if there are no current jobs.Whoreson
@Chromatin I was reading the description of your problem in the comments of the other answer and it seems that a single thread executor is exactly what you are looking for.Whoreson
It works great. Executors is a gold mine. Thank you for pointing it out.Chromatin

© 2022 - 2024 — McMap. All rights reserved.