Multi-threading with Swing - java

I am trying to write a multi-thread program with Swing. Essentially how the program works is that when it runs it will have a robot(represented by a circle in screenshot) that is wondering around in a field. This robot should be controlled by a thread of it's own. The program has a button "Launch Robot" that will create another robot on the field(upto a max of say 10). Right now I have the basics of the program, but it all runs under one thread. I can launch as many robots as I want but they all run under a single thread. But I want that whenever I click "launch Robot" an independent thread be created and control that robot. This is how the program looks right now:
The UML diagram for the program is as following:
Since its a bit long I won't post the whole program. But the method that starts and updates the robots(currently controlling only one robot on the field) is as follows:
public void gameStart(){
Thread gameThread = new Thread(){
public void run(){
while(true){
//execute one time step for the game
gameUpdate();
//refresh screen
repaint();
//give other threads time
try{
Thread.sleep(1000/UPDATE_RATE);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
};
gameThread.start();
}
My question is how can I achieve multi-threading for such a scenario? I know the basics of SwingWorker, but since I haven't done any multi-threading, I have no idea on how to make several threads work and be updated by one thread(update position of robots that are controlled by threads).
EDIT: Just to make my point, this is a project that I am working on. It's not about if multi-threading makes sense in this scenario or not.

Create a RobotModel that contains a Collection<Robot> and defines their interaction. Iterate the model in the doInBackground() implementation of a SwingWorker. Invoke publish() as meaningful events arise, and process() updates to the RobotWorld view by querying the model. As discussed here, there should be no drawing in the model and no interaction logic in the view. A single worker should suffice for a moderately complex model, but you can synchronize multiple workers as shown here.

A good option to achieve this is to use ScheduledThreadPoolExecutor.
Instantiate the thread pool via:
ScheduledThreadPoolExecutor threadsPool = new ScheduledThreadPoolExecutor(size);
To create a new Robot Thread, use:
threadsPool.submit(new Runnable() {
#Override
public void run() {
launchRobot();
}
});
This way, each invocation will instantiate a new Thread.
You can set the limit of the total number of allowed Thread via the "size" argument.
You can also pass a result after each thread completes using:
public <T> Future<T> submit(Runnable task, T result)
If you want less detail, you could let Java do the work for you with the following convenience API:
Executors.newCachedThreadPool() (unbounded thread pool, with automatic thread reclamation) or:
Executors.newFixedThreadPool(int) (fixed size thread pool)
Remember us, Executor. Remember what was done here today. And may Adun watch over you

This robot should be controlled by a thread of it's own.
Why?
IMO, the most important way to describe any thread is to say what it waits for. In an internet server, an accept thread waits for incoming connections from new clients, and a client thread waits for additional commands from a single client. In a program that performs massive parallel computations, a worker thread waits for tasks to be performed. In a GUI program, the event dispatch thread waits for keyboard and mouse events. Etc., etc.
What will your robot thread wait for?
If it waits for time to pass (i.e., if it calls Thread.sleep()), then your GUI framework probably already has a timer thread that does that, and you might want to consider using it. (In Swing, you would use the javax.swing.Timer class to submit new timed tasks.)

Related

Java SystemTray blocks GUI? [duplicate]

I am fairly new to java, and am starting to get into using different threads in order to use wait() or sleep() on one part of my code and have the others still run.
For this project, I am using JFrame with the javax.swing.* and java.awt.* imports. What I am trying to do is have one of the threads (in my code it is the main, starting thread) allow the player to choose a space on the tic tac toe board, and when they click it, it will change icons, and then the AI will wait for 1 second before playing back from the second thread that I created.
Unfortunately, whenever I call ait.sleep(1000) (ait is my thread name) both threads wait for 1 second before finishing their execution. Can anyone tell me why sleeping one thread is stopping my whole execution?
Can anyone tell me why sleeping one thread is stopping my whole
execution
to better explain your Swing GUI is created on its own special thread separate from that which main() and other code will run in, this is done via creating your Swing components in the SwingUtilities.invokeXXX block (even if you have not done this your GUI will be run on a single thread called the initial thread) . Now if you simply call sleep while on Event Dispatch Thread (or for that matter on the same Thread) it will wait for the call to Thread.sleep to finish. Now because all Swing events are processed on EDT we pause its execution by calling sleep(..) thus pausing the UI events from being processed and therefore GUI is frozen (until sleep(..) returns).
You should not use Thread.sleep(..) on Event Dispatch Thread (or any Thread where sleep will cuase unwanted execution blocking), as this will cause the UI to seem frozen.
Here is a nice example which demonstrates exactly, this unwanted behavior caused by invoking Thread.sleep(..) on GUI's EDT.
Rather use:
Swing Timer for example:
int delay=1000;// wait for second
Timer timer = new Timer(delay, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
//action that you want performed
}
});
//timer.setRepeats(false);//the timer should only go off once
timer.start();
Swing Worker
or if no Swing components are being created/modified:
TimerTask
Thread, you would then use Thread.sleep(int milis) (but thats last option in any case IMO)
UPDATE
Swing Timer/SwingWorker was only added in Java 1.6, however, TimerTask and Thread have been around for alot longer sine Java 1.3 and JDK 1 repsectively, thus you could even use either of the 2 above methods and wrap calls that create/manipulate Swing components in SwingUtilities/EventQueue#invokeXX block; thats the way things used to be done :P
Thread.sleep is a static method. Invocations of it via the reference of any given Thread is simply a form of convenience.
As a result, any invocation of sleep is really calling sleep on the current Thread, which I suspect is the Event Thread in your case. Sleeping/blocking on the Event Thread will give the appearance of being locked up.
If you want the ait thread to sleep, then code that thread to sleep. Designs where one thread "reaches into" another and pushes it around at a low level are fundamentally broken. You write the code for every thread, so write it to do what you want it to do in the first place so you'll find no need to reach into it from the outside.
Which makes more sense, for the person in the kitchen to know how to cook breakfast or the person in the bedroom to yell down and direct them to perform each step of making breakfast? Sure, you might tell them to make breakfast. But you definitely don't direct each step at a low level.
Thread.sleep is a static method which causes the currently executing thread to sleep for the specified amount of time. Java syntax allows you to call a static method via a variable, but the compiler simply uses the compile-time type of that variable to determine which method to call, i.e.
Thread ait = null;
ait.sleep(1000); // calls Thread.sleep(1000), causing current thread to sleep.
// In particular, does *not* NPE
You also mentioned wait() - while this is an instance method rather than a static it still causes the current thread to do the waiting (ait.wait(1000) would cause the current thread to wait for up to 1 second or until another thread calls ait.notifyAll()).
There is a Thread.suspend() and its counterpart resume() that were introduced in the very early days of Java to allow one thread to control another, but they were deprecated soon after as they are inherently deadlock-prone. The recommended pattern if you want one thread to "control" another is to do it co-operatively, i.e. have some kind of shared flag that thread A sets and thread B reads, and have B send itself to sleep according to the flag:
volatile boolean threadBShouldRun = true;
// Thread B
while(true) {
if(threadBShouldRun) {
// do some stuff
} else {
Thread.sleep(1000);
}
}
// Thread A
if(someCondition) {
threadBShouldRun = false;
}
but it's generally easier and less error-prone to make use of the facilities that exist in the java.util.concurrent package. Doing multi-threading right is much harder than it appears on the surface.

Java Swing making the thread wait once

I'm trying to make my GUI wait for 2 seconds after a recent update in the graphics. It means that after I use:
boardLogo.repaint();
boardLogo.revalidate();
I want the GUI to wait before making further computations and then paint them again.
The code:
SwingUtilities.invokeLater(new Runnable() {
#SuppressWarnings("rawtypes")
#Override
public void run() {
SwingWorker swingWorkerExample = new SwingWorker(){
#Override
protected Object doInBackground() throws Exception {
return null;
}
protected void done(){
try {
Thread.sleep(2000); //wait 2 seconds.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
swingWorkerExample.execute();
}
});
//.... more code here
boardLogo.repaint();
boardLogo.revalidate();
But when I run it - first it executes the last two lines, then waits for 2 seconds...
To be honest, my knowledge about Threads and Java Swing is not the best (especially when it comes to understanding swing worker, which I've tried to read about from Oracle site), so I would appreciate it if the answer will be detailed.
Thanks!
when I run it - first it executes the last two lines, then waits for 2 seconds ... my knowledge about Threads and Java Swing is not the best.
You say, it executes the last two lines. Ever stop to wonder what it is?
It is a thread. Threads are what execute code in a Java program, and every line that gets executed is executed by some thread.
When your code calls invokeLater(), it is submitting a task (i.e., a piece of code) to be executed by Swing's event dispatch thread (EDT); and when your code calls swingWorker.execute() it is submitting a task to be performed by one of Swing's background threads.
The whole point of having more than one thread in a program is that they can be doing different things at the same time.
In your case, you've got the EDT sleeping for two seconds while, at the same time, some other thread is calling boardLogo.repaint(); and boardLogo.revalidate();
There's a couple of important things to know about Swing and multi-threading:
All of your event handlers will be run by the EDT.
An event handler should never do anything that takes more than a small fraction of a second, because your application will not be able to respond to any other events (i.e., it will appear to be "hung") until the handler returns.
No other thread is allowed to interact with any of Swing's GUI components.
One important use-case for invokeLater() is, it's how code running in the background thread can communicate with GUI components. invokeLater() submits a task (i.e., a piece of code) that will be run in the EDT.
The main use-case for SwingWorker is pretty much the opposite of that: It's how an event handler, running in the EDT, can kick off a task that is going to take more than a small fraction of a second to complete.
You can learn about this stuff by working your way through the Swing Concurrency tutorial: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/

Deadlock between different event threads

I'd always worked in java with the understanding that if I farmed off a task to the event thread, it could use any suitiable locks it needed and it would never bump into with any other locks I made from the event thread.
Unfortunately, my webstart program has three event threads, and two of them are deadlocking.
I have AWT-EventQueue-0 in the main thread-group
This hangs inside a paint operation, trying to perform a getRowColor() operation to prepare a renderer for a table cell. As it's painting, it has the component tree-lock.
I have AWT-EventQueue-1 of the javawsSecurityThreadGroup which seems harmless enough, it looks like it might be uninvilved in the hangs, but it does get hung up on an invalidate() call for a text component (Java console?)
Lastly, I have AWT-EventQueue-2, of the javawsApplicationThreadGroup.
This particular component obtains a write-lock for purpose of setting the table data (which blocks reads against row color). This then stalls on an update of the focused cell, which flows down scrollRectToVisible(), validateView(), updateCursor(), findComponentAt(), which needs the tree-lock held by the paint operation underway on AWT-EventQueue-0
The read-lock/write-lock is our code, and exists to let programmers worry less about threading. I'm not prepared to axe it just because the application decides it needs extra event threads to run in parallel.
Ultimately, I want our application using a single AWT-EventThread. Is there a way to get one of the event thread to farm requests off to the other? Or to select which event thread is used for painting, or used when an invokeLater()/invokeAndWait() happens?
I'm not sure if it matters, but we do make use of FX in our application.
Try reducing the scope of the critical sections guarded by your write locks to only writing to memory.
If you push from the critical section the subsequent notifications to update the UI, which depend on the write but are not part of the critical section for the write, and allow them to use the read lock via other control paths, your deadlock issues should resolve.
Another option may be to fork your write tasks to background threads (maintaining proper synchronization; see also java.util.concurrent.ExecutorService) and then send notifications when writes are complete that can be executed asynchronously in the display thread.
I don't have this figured out to a fair-thee-well yet, but I think I've got enough for anyone to chase it back to a final solution. I'll note, evidently my environment is in some way unique to Macintosh computers, as I'm not the first person looking at this problem on a Macintosh system, and I've never before encountered this problem under a Windows setting.
Java-Webstart kicks things off. It invokes the application main() method with a thread in the Thread Group titled javawsApplicationThreadGroup. This puts the thread in an appropriate application context, which causes any AWT/Swing calls to be passed off to the AWT-EventQueue-2, which is in this thread group.
This includes not only invokeLater(), but repaint() calls as well.
We also start up JavaFX from this thread. For whatever reason, it puts the JavaFX Application Thread in the "system" threadgroup. The system threadgroup is a bit tricky, the dev tools I use (Eclipse IDE/JProfiler) don't normally show threads in this group, making it a poor choice for anything. We will also hand off requests from FX to Swing from here using InvokeLater(), and I'm sure no shortage of repaint()s. I've not verified this directly, but quick emperical tests suggests requests from the FX Application Thread under the "system" go to the AWT-EventQueue for the "main" threadgroup.
This at least explains what I'm looking at and gives me the tools I need to combat the problem.
First steps to resolving this: Top of the main method, I locate the "main" threadgroup and kick off a new thread in that group to perform the actual application startup. This causes both the FX Application Thread to spawn under the main thread group, as well as our main thread-pool. Result, both FX and background tasks submit swing requests to the same event queue. This doesn't quite fix everything for me (still have some business logic running from threads in the javawsApplication thread group), but I think it gives me all the tools I need to reach a solution.
public static void main(String[] args)
{
startFromMainThreadGroup(args);
}
private static void startFromMainThreadGroup(final String[] args)
{
ThreadGroup tgSystem = Thread.currentThread( ).getThreadGroup( );
ThreadGroup ptg;
while ( (ptg = tgSystem.getParent( )) != null )
{
tgSystem = ptg;
}
ThreadGroup tgMain = null;
ThreadGroup[] groups = new ThreadGroup[tgSystem.activeGroupCount() + 16];
int numGroups = tgSystem.enumerate(groups);
for(int i = 0; i < numGroups; i++)
{
if("main".equals(groups[i].getName()))
{
tgMain = groups[i];
break;
}
}
if(tgMain == null)
{
tgMain = tgSystem; // Fallback
}
Runnable doRun = new Runnable()
{
#Override
public void run()
{
mainImpl(args);
}
};
Thread thread = new Thread(tgMain, doRun, "mainFork");
thread.setDaemon(false); // Explicit
thread.start();
}

What's proper way to make my own events in java

I'm student and I'm working on project with few of my friends. My task is to make something like class library. Classes in this library should provide API for my friend who must make GUI part of application. GUI could be made by any toolkit (Swing, JavaFX, SWT, AWT, all should work, in fact, it should work even if there is no GUI). I need to make class that waits for data to arrive from network. I don't know when data will arrive, and UI must be responsive during waiting, so I put that in different thread. Now problem is how to make GUI respond when data arrive. Well, I tought that this is asynchronous event and GUI should register event handlers, and I should call that methods when event happens. I proposed this solution:
interface DataArrivedListener{
void dataArrived(String data);
}
class Waiter{
private DataArrivedListener dal;
public void setDataArrivedListener(DataArrivedListener dal){
this.dal = dal;
}
void someMethodThatWaitsForData(){
// some code goes here
data = bufRdr.readLine();
//now goes important line:
dal.dataArrived(data);
// other code goes here
}
}
My question is:
Should I replace "important" line with something like this:
java.awt.EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or something like:
javafx.Platform.runLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or maybe I should do something completely different?
Problem is that I'm not sure which of this will work for any type of UI. If it's GUI, dataArrived() could potentialy make changes to GUI and no matter what type of GUI it is, this changes should be drawn on screen properly. I also think that it is better if I do "invoke this code later" so that my someMethodThatWaitsForData() method could trigger event and continue on with it's on work.
I appreciate your help.
Here's an Event Listener article I wrote a while back. The article explains how you write your own event listeners.
You're correct in that you want to write your own event listeners if you want your library to work with any GUI.
I'm most familiar with Swing, so yes, you'll have GUI code that looks like this:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
dal.buttonPressed(data);
}
});
If you want it to be completely agnostic to what GUI is being used the only real solution is to let the receiver handle it in dataArrived. Since every toolkit has its own implementation all you can really do to make it work with any toolkit is to disregard it. Otherwise what you will actually end up with is a list of "supported toolkits" and a case for each one.
If you just want dataArrived to be executed away from someMethodThatWaitsForData then you could make your own dispatch thread or make a new thread each time.
If you want to be truly independent of any front-end system, I would recommend creating two threads. The first is your Waiter, which will just listen for events and put them into a Queue of some sort (see the "All Known Implementing Classes" section). The second will invoke the data listener or listeners whenever the queue is not empty.
The concept of invoking a Runnable in the background is kind of deprecated since the invention of the concurrent package. The main reason that this was done in earlier days, is that the GUI code needs to be executed in a different thread, to guarantee that it stays responsive, even if the main thread is busy doing some calculations, but actual multi-threading was still in its very early days. The resulting invokeLater concept works, but comes with a strong creation overhead. This is especially annoying if you frequently have to do minor things, but each time you need to create an entire new Runnable, just to get that event into the Swing thread.
A more modern approach should use a thread-safe list, like a LinkedBlockingQueue. In this case any thread can just throw the event into the queue, and other listener/GUI-Event-handlers can take them out asynchronously, without the need of synchronization or background Runnables.
Example:
You initialize a new Button that does some heavy calculation once it is pressed.
In the GUI thread the following method is called once the button is clicked:
void onClick() {
executor.submit(this.onClickAction);
}
Where executor is an ExecutorService and the onClickAction a Runnable. As the onClickAction is a Runnable that was submitted once during Button creation, no new memory is accessed here. Let's see what this Runnable actually does:
void run() {
final MyData data = doSomeHeavyCalculation();
dispatcher.dispatch(myListeners, data);
}
The dispatcher is internally using the LinkedBlockingQueue as mentioned above (the Executor uses one internally as well btw), where myListeners is a fixed (concurrent) List of listeners and data the Object to dispatch. On the LinkedBlockingQueue several threads are waiting using the take() method. Now one is woken up as of the new event and does the following:
while (true) {
nextEvent = eventQueue.take();
for (EventTarget target : nextEvent.listeners) {
target.update(nextEvent.data);
}
}
The general idea behind all this, is that for once you utilize all cores for your code, and in addition you keep the amount of objects generated as low as possible (some more optimizations are possible, this is just demo code). Especially you do not need to instantiate new Runnables from scratch for frequent events, which comes with a certain overhead. The drawback is that the code using this kind of GUI model needs to deal with the fact that multi-threading is happening all the time. This is not difficult using the tools Java gives to you, but it is an entire different way of designing your code in the first place.

using sleep() for a single thread

I am fairly new to java, and am starting to get into using different threads in order to use wait() or sleep() on one part of my code and have the others still run.
For this project, I am using JFrame with the javax.swing.* and java.awt.* imports. What I am trying to do is have one of the threads (in my code it is the main, starting thread) allow the player to choose a space on the tic tac toe board, and when they click it, it will change icons, and then the AI will wait for 1 second before playing back from the second thread that I created.
Unfortunately, whenever I call ait.sleep(1000) (ait is my thread name) both threads wait for 1 second before finishing their execution. Can anyone tell me why sleeping one thread is stopping my whole execution?
Can anyone tell me why sleeping one thread is stopping my whole
execution
to better explain your Swing GUI is created on its own special thread separate from that which main() and other code will run in, this is done via creating your Swing components in the SwingUtilities.invokeXXX block (even if you have not done this your GUI will be run on a single thread called the initial thread) . Now if you simply call sleep while on Event Dispatch Thread (or for that matter on the same Thread) it will wait for the call to Thread.sleep to finish. Now because all Swing events are processed on EDT we pause its execution by calling sleep(..) thus pausing the UI events from being processed and therefore GUI is frozen (until sleep(..) returns).
You should not use Thread.sleep(..) on Event Dispatch Thread (or any Thread where sleep will cuase unwanted execution blocking), as this will cause the UI to seem frozen.
Here is a nice example which demonstrates exactly, this unwanted behavior caused by invoking Thread.sleep(..) on GUI's EDT.
Rather use:
Swing Timer for example:
int delay=1000;// wait for second
Timer timer = new Timer(delay, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
//action that you want performed
}
});
//timer.setRepeats(false);//the timer should only go off once
timer.start();
Swing Worker
or if no Swing components are being created/modified:
TimerTask
Thread, you would then use Thread.sleep(int milis) (but thats last option in any case IMO)
UPDATE
Swing Timer/SwingWorker was only added in Java 1.6, however, TimerTask and Thread have been around for alot longer sine Java 1.3 and JDK 1 repsectively, thus you could even use either of the 2 above methods and wrap calls that create/manipulate Swing components in SwingUtilities/EventQueue#invokeXX block; thats the way things used to be done :P
Thread.sleep is a static method. Invocations of it via the reference of any given Thread is simply a form of convenience.
As a result, any invocation of sleep is really calling sleep on the current Thread, which I suspect is the Event Thread in your case. Sleeping/blocking on the Event Thread will give the appearance of being locked up.
If you want the ait thread to sleep, then code that thread to sleep. Designs where one thread "reaches into" another and pushes it around at a low level are fundamentally broken. You write the code for every thread, so write it to do what you want it to do in the first place so you'll find no need to reach into it from the outside.
Which makes more sense, for the person in the kitchen to know how to cook breakfast or the person in the bedroom to yell down and direct them to perform each step of making breakfast? Sure, you might tell them to make breakfast. But you definitely don't direct each step at a low level.
Thread.sleep is a static method which causes the currently executing thread to sleep for the specified amount of time. Java syntax allows you to call a static method via a variable, but the compiler simply uses the compile-time type of that variable to determine which method to call, i.e.
Thread ait = null;
ait.sleep(1000); // calls Thread.sleep(1000), causing current thread to sleep.
// In particular, does *not* NPE
You also mentioned wait() - while this is an instance method rather than a static it still causes the current thread to do the waiting (ait.wait(1000) would cause the current thread to wait for up to 1 second or until another thread calls ait.notifyAll()).
There is a Thread.suspend() and its counterpart resume() that were introduced in the very early days of Java to allow one thread to control another, but they were deprecated soon after as they are inherently deadlock-prone. The recommended pattern if you want one thread to "control" another is to do it co-operatively, i.e. have some kind of shared flag that thread A sets and thread B reads, and have B send itself to sleep according to the flag:
volatile boolean threadBShouldRun = true;
// Thread B
while(true) {
if(threadBShouldRun) {
// do some stuff
} else {
Thread.sleep(1000);
}
}
// Thread A
if(someCondition) {
threadBShouldRun = false;
}
but it's generally easier and less error-prone to make use of the facilities that exist in the java.util.concurrent package. Doing multi-threading right is much harder than it appears on the surface.

Categories