I'm writing a chess program in java. So far things are coming along fine but I do have a problem with updating my UI.
Here's a snippet of code from class ChessBoard which extends JPanel. This is called when a user tries to make a move:
if ( isLegalMove( aMove ) ) { // If the move's legal
makeMove( aMove ); // Make that move
select = null; // Reset some info
drag = null;
toggleTurn(); // Change turns
generateMoves( 0 ); // Get legal moves for CPU
repaint(); // Redraw board
thread.run(); // Run chess algorithm
}
The thread is calling "run" on my instance of ChessBoard. The algorithm that finds the move can take several seconds to decide on a move.
I would like for my UI to update to reflect the user's move and then run the algorithm. That's why I run the algorithm on a separate thread. But my UI is not being updated until the computer also makes a move.
So if the user clicks a space to send a piece there, the screen freezes and then all of a sudden the piece has moved but the computer has moved also and it is again the player's turn.
Any help will be greatly appreciated.
thread.run() is going to execute the code in the thread's run method on the current thread. You want thread.start().
Relevant JavaDoc
The repaint method doesn't actually repaint immediately. It basically tells the JPanel that it ought to repaint itself soon. Then you go ahead on the same thread and calculate the AI's move, which will freeze the window because Swing isn't multi-threaded.
First, threads are not re-entrant (I'll explain that in a moment).
thread.run() is not causing the thread to execute in a separate thread, it's just call the run method of the thread (within the current Threads context.
What you need to do is set up a condition loop within your Thread that you can trigger in order to execute the logic you need.
public class ChessThread extends Thread { // I prefer Runnable, that's me
protected static final Object NEXT_MOVE_LOCK = Object();
public ChessThread() {
setDaemon(true); // This will allow the JVM to exit without the need to terminate the thread...
}
public void doNextMove() {
// Notify the "wait" that we want to continue calculating the next move
synchronized (NEXT_MOVE_LOCK) {
NEXT_MOVE_LOCK.notify();
}
}
public void run() {
while (true) {
// Wait for the "next move" request
synchronized (NEXT_MOVE_LOCK) {
try {
NEXT_MOVE_LOCK.wait();
} catch (InterruptedException exp) {
}
}
// Calculate the next move...
}
}
}
Now, Threads are non-reentrant, this means that once the run method has complete, that instance of the Thread can not be restarted.
Hence using thread.start() more then once will not work (can't remember if it throws an exception or not) (hence the reason I prefer Runnable)
So. What you want to do, is start the Thread when your program loads and when you need to, call thread.doNextMove() to cause it calculate the what ever it is you need.
Now, also remember, Swing is not Thread safe. That is, you should NEVER update the UI from any Thread other than the Event Dispatching Thread (or EDT)
You might also want to have a read through Concurrency in Swing
Oh and Concurrency in Java
Related
So say there are 3 threads (t1, t2, t3) spawned off the main thread. How would I ensure that a particular thread finishes its execution first and another thread as last. I don't mean to begin a thread after the "completion" of another, but want to ensure they finish in a particular order.
A sample code will be extremely helpful.
To be more precise, say in a gaming application, you would want to change the graphics first, then you want the sound to be produced followed by the score update.
You may use wait() and notify(). It is a mechanism through which we can send signals between threads.
wait()causes the thread to pause in the critical region. While paused the thread releases its lock. It must be called inside synchronization block or method.
notify() will send signal to one of the threads waiting for the same object.. It wakes up the thread that have called notify().
Here is an example with two of your functions: display and sound. Display would be completed before sound:
(You may add third one (score) also.)
class shared
{
synchronized void disp()
{
System.out.println("Display thread complete");
notify();
}
synchronized void play_s()
{
try
{
wait();
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("Sound thread complete");
}
}
class display extends Thread
{
shared sh;
public display(shared sh,String str)
{
super(str);
this.sh=sh;
start();
}
public void run()
{
sh.disp();
}
}
class sound extends Thread
{
shared sh;
public sound(shared sh,String str)
{
super(str);
this.sh=sh;
start();
}
public void run()
{
sh.play_s();
}
}
public class sync {
public static void main(String agrs[])
{
shared sh=new shared();
display d=new display(sh,"one");
sound s=new sound(sh,"two");
}
}
"To be more precise, say in a gaming application, you would want to change the graphics first, then you want the sound to be produced followed by the score update."
That requires sequential execution of the externally visible activities. The graphics update has to happen in the event handling thread, and that seems to be the obvious place to sequence the activities.
I would separate out any computationally intensive or otherwise time consuming preparations for each activity, and delegate it to a thread or thread pool, without worrying about order. Use e.g. invokeLater to notify the event handling thread when the computation has been done. In the event handling thread, keep track of the conditions for doing something, such as changing the score. When all conditions have been met, including completion of all pre-conditions, do the action.
Your question doesn’t make much sense as the finishing of a thread has no impact on the state of the application and hence, the finishing order is completely irrelevant as well. It’s very likely that what you are actually trying to achieve needs a different solution.
This is illustrated by your example: “say in a gaming application, you would want to change the graphics first, then you want the sound to be produced followed by the score update”. Here you are describing actions that you want to be performed one after another, which entirely contradicts your statement “I don't mean to begin a thread after the "completion" of another”.
What you probably meant is that you want to load or calculate resources, e.g. graphics and sound, concurrently but want to render them in order. Therefore the key point is to split the loading/calculation from the rendering into two dependent tasks. Then, while the graphic rendering task only depends on the completion of the graphics creation, the sound rendering depends on both, the sound data creation and the completion of the graphics rendering, to establish your desired order. So it’s not the finishing of the sound thread that depends on the finishing of the graphics thread but it’s the beginning of the sound rendering that depends on the finishing of the graphics rendering.
There are a lot of ways to implement such things but given how abstract your question is, it’s way too broad.
However, regarding your original question, there is Thread.join(). When the code executed by thread T2 invokes that method on thread T1 it will wait for the termination of T1, thus the thread T2 will not terminate before T1. But, as said, placing such a wait at the end of T2 would not make much sense as the finishing order of the threads is meaningless. You would have to place it before the beginning of the dependent action.
As part of my efforts to implement a voice recognition program in Java I have implemented the actual voice recognition code in a separate thread. The main thread handles the GUI interface and receives constant updates from the voice recognition thread when words are identified.
When the user clicks the Quit button in the GUI on the main thread I want this thread to immediately run some clean-up code and terminate.
I currently have the following:
public class VoiceRecognitionCore extends SwingWorker<List<String>, String>
{
//Variables and things here
#Override
public List<String> doInBackground() throws VoiceRecognitionException
{
//Code here
while(continueVoiceRecog == true)
{
//More code
Result result = recog.recognize();
//More code
}
}
}
Where I rely on the while loop to constantly check the status of continueVoiceRecog which will be set to false by the main thread when the user clicks "Quit".
The current problem is that the code can sometimes permanently sit inside the recog.recognize() method so it'll never get back to the while check. It should be noted that this was always intended as a temporary solution.
I'm thinking of extending doInBackground() to catch InterruptedException and will use a thread interrupt which will call a cleanup method to deallocate any resources being used.
What is the safest/best approach for this scenario? If it is what I propose, are there any potential issues I should be aware of?
Using thread interrupt is perfectly acceptable route - however in your example (using SwingWorker) you can use the cancel() method instead.
In the calling code after having created the VoiceRecognitionCore you can cancel() the worker exit button action listener:
final VoiceRecognitionCore worker = new VoicRecognitionCore();
worker.execute();
JButton exitButton = new JButton("Exit");
exitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// True passed to Interrupt the underlying thread.
worker.cancel(true);
// other clean-up
// then System.exit(0); ?
}
});
However, this approach will need to check the status of: Thread.isInterrupted() within your recognize() method. (see link: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/cancel.html)
If you are needing to clean-up stuff and don't have ability to check the isInterrupted() flag - perhaps best approach is to have a method to be able to determine if your recog object is mid recognizing... and when the exit button is pressed - if recog.isRecognizing() then do clean up and then exit?
PS. One might argue that if you are doing a System.exit(0); anyway, then cleanly exiting that loop is perhaps unnecessary ... but it depends if you are doing other clean-up in there... such as finishing writing to files etc.
I was looking at the current thread:
How to create a thread that waits for a boolean variable to become true?
Everyone seemed to disagree with each other and noone exaplined themselves enough so I shall present this in the easiest way. Here is my code as of today.
boolean connecting = false;
public static void main(String[] args) {
initUI();
while(true) {
if(connecting) {
connecting = false;
doSomething();
}
};
}
initUI() is a mthod which initiates the User Interface. When the user clicks a button in that class called "Connect" it will call it's action listener and set the boolean "connecting" to "true". When it enters the if area it will then reset the boolean to "false" and run the code which I want.
This works, however... It uses far too much CPU.
If I directly set the buttons action listener to the doSomething() method the program jams (and should) as the action listener method needs to finish in order for the button to reset. However the doSomething() has loops (it's a chat program) so it will not return to the original while (which is displayed here in code) until he disconnects.
So my question, is there anyway to "wait" for the boolean to change to true. For example a listener?
ANSWER: Thanks to Joni I implemented a Thread.
The buttons actionListener now includes:
(new connectThread()).start();
And my thread looks like this:
public class connectThread extends Thread {
public void run() {
ui.btn.setEnabled(false);
doSomething();
ui.btn.setEnabled(true);
}
}
As for the question title, waiting for a boolean to change, as another person explained an event listener could be set.
So my question, is there anyway to "wait" for the boolean to change to true.
You can't do it (efficiently and responsively) with a bare boolean variable. A sleep / test loop is a poor solution because it will either be expensive or non-responsive. If the sleep interval is small you waste CPU, and if you make it larger your application takes a (relatively) long time to notice the state change.
But if the boolean is updated via a method (e.g. a setter) then you can code the setter to:
notify other threads that are waiting in a mutex; e.g. https://stackoverflow.com/a/12884570/139985, or
call some "event listener" callback.
Go back to the code where the event listener calls doSomething(), but with one change: start a new thread that runs doSomething() rather than call it directly. You can find a complete example of how to do this in the Java Tutorial: Simple Background Tasks. The SwingWorker API documentation also has an example.
You are on the wrong track - "busy waiting" as you are doing here is almost always the wrong idea, since it just needlessly burns CPU time.
From what I understand you want to react to a button-press without locking up the UI thread. There is no need to have the thread already waiting before that point - just start it up once the button is pushed, as Joni suggests. If you want to ensure that only one button press is processed at a time, you could use a thread pool with a single thread (see SingleThreadExecutor).
I also want to point out an important mistake in your example code: connecting needs to be made volatile to tell the compiler that the value could change from another thread. As it is, there is no guarantee that your worker thread will ever see the value change, so it could just loop infinitely even if you set connecting to true in another thread.
You can either put in a Thread.sleep(100); in the loop, so it's not a tight loop like that, which can easily freeze the rest of the threads.
What you can also do is use a wait/notify mechanism. Just have a shared Object, signaller... have the "while(true)" call "signaller.wait()", then, after your other thread sets the flag (it might not need to), it can call "signaller.notifyAll()" which will let the other thread run its next iteration, and see that the flag is set.
In your listener, instead of setting a flag, you could run doSomething() in a new thread. In the example below, ThreadTest is actually the class where you currently have your listener method (I've called it onClick()).
public class ThreadTest {
private ExecutorService service;
public ThreadTest() {
service = Executors.newFixedThreadPool(10);
}
// Button click listener.
public void onClick() {
service.submit(new Runnable() {
#Override
public void run() {
doSomething();
}
});
}
public void doSomething() {}
}
Apparently all Eclipse/SWT has in the way of managing the busy mouse indicator is
BusyIndicator.showWhile(Runnable synchronousStuffToDo)
However, I have a fundamentally event-oriented project where "stuff to do" doesn't happen within a sequential line of execution: an action gets ordered and a continuation-callback is provided to the execution manager. Therefore I have nothing meaningful to put into that synchronousStuffToDo runnable.
Is there another, however low-level and clumsy, but platform-independent way of manipulating the busy indicator asynchronously, which means two separate method calls, "activate it" and "deactivate it"?
I should add ProgressMonitorDialog to this question because it appears to suffer from the same problem. Yes, within the ProgressMonitorDialog#run method an inner event loop will be spinned, but SWT event loop is just one of my execution managers, so the chain will still be broken. Apparently without this class I can't even show a progress monitor except if I reimplement from lower-level primitives.
There is no way you can manipulate the Cursor using the BusyIndicator class.
You can invoke the below util method to show a Busy Icon while running your job on a background Thread
public static void imBusy(final boolean busy){
Display.getDefault().asyncExec(new Runnable()
{
#Override
public void run()
{
Shell shell = Display.getDefault().getActiveShell();
if(busy){ //show Busy Cursor
Cursor cursor = Display.getDefault().getSystemCursor(SWT.CURSOR_WAIT);
shell.setCursor(cursor);
}else{
shell.setCursor(null);
}
}
});
}
Your runnable should wait for the task completion. E.g. (code written in browser, will not compile - I'm ignoring exceptions):
final Object condition = new Object();
BusyIndicator.showWhile(new Runnable() {
public void run() {
synchronized(condition) {
while (!isMyTaskDoneFlag()) {
condition.wait();
}
}
}
});
doTask(new MyTask() {
public void perform() {
try {
// Task logic
...
} finally {
// When done
setMyTaskDoneFlag();
synchronized(condition) {
condition.notify();
}
}
}
});
Make sure all code paths in your tasks do not forget to unblock the runnable. Pretty much the same approach can be used with progress monitors - you may wake your runnable to update progress monitor value.
Note: You need to make sure the waiting runnable is not executed on SWT thread (e.g. set fork to true if running in progress monitor) or else your application will become unresponsive.
I found a solution (which I don't particularly like, but it works) in an older SWT application I'm working on now. It uses BusyIndicator#showWhile, and the synchronous stuff it does inside is:
Start the asynch task in a background thread
Loop waiting for the background thread to finish up while at the same time spinning the
SWT event loop explicitly:
while (!taskDone){
if (!display.readAndDispatch() && !shell.isDisposed()) {
display.sleep();
}
taskDone = //check for task progress
//update something on the main window status bar
}
I'm trying to convert this to something cleaner (along the lines of what Marko suggested):
Set the busy icon
Submit background task
Unset the busy icon
but I'm not sure what would be best for updating the status bar (background tasks are actually remote calls so their thread is blocked until they finish up). I'm thinking of having a dedicated thread that detects when background jobs are running and update the status bar accordingly (the update is just an unfolding dotted line, nothing task specific), but using a thread just for this seems a bit of a waste.
public static void moveTo(Coordinate destination) {
changeState(State.NAVIGATION);
controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));
dmc.moveTo(destination);
changeState(State.IMMEDIATE);
controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
}
In this code, the addRemote method updates the controlPnl GUI with new buttons. The dmc.moveTo method has up to two Thread.sleep calls in it, and I think that they are being called before the controlPnl GUI is being updated. I've commented out the two method calls after dmc.moveTo which change the GUI back to what it was before the call, and the controlPnl doesn't finish updating until moveTo finishes executing. What I need is for the GUI to finish updating before the moveTo method starts executing and puts the Thread to sleep. Is there any way that I could accomplish this in Java 6?
In case it matters, the moveTo method moves a LEGO Mindstorm robot to a specified point on a path defined by the user. The GUI that is being updated provides Swing components (JButtons and JRadioButtons) for the user to control the robot with while it's navigating. The addRemote method changes the set of Swing components for the user to use, and the moveTo method sends commands to the robot to actually execute the movement (by telling its motors to move, sleeping for the correct amount of time, then telling its motors to stop moving). I'm using a state machine pattern, and this method is part of the controller which handles events from the UIs.
You have a single GUI thread. Don't use it to call other things; if you do, those things have to complete before anything else is going to happen in your GUI.
At the very least you would want to start a new thread to perform your dmc.moveTo(destination). More than likely this isn't the only place you're doing this, and probably want an Executor set up to perform these tasks.
Without knowing more about your code (especially since you're using a static method) I can't comment on how you would want to set up the Executor but the simplest example of using a Thread would be:
public static void moveTo(final Coordinate destination) {
changeState(State.NAVIGATION);
controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));
new Thread(new Runnable() {
public void run() {
dmc.moveTo(destination);
changeState(State.IMMEDIATE);
controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
}
}).start();
}
This creates a new Thread that executes your (anonymous) Runnable which performs your moveTo(). Note this is far less efficient than having an Executor that is ready to run your task; it has to create a new Thread every time. However, if that's not an issue in terms of the performance you need then it's perfectly fine. Also note that because I'm referencing destination directly inside the anonymous inner class, it has to be declared final when passed into your method.
Since your moveTo takes a long time you should not execute it on the main event handling thread. Instead, have moveTo update the GUI and start the actual movement in a separate thread. Once the movement is complete, use SwingUtilities.invokeLater to do the second set of GUI updates.
private static ExecutorService executor = Executors.newCachedThreadPool();
public static void moveTo(final Coordinate destination) {
changeState(State.NAVIGATION);
controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));
executor.execute(new Runnable() {
public void run() {
dmc.moveTo(destination);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
changeState(State.IMMEDIATE);
controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
}
});
}
});
}
This way moveTo does the initial set of GUI updates and then returns immediately, freeing the event loop to keep the GUI responsive, but the second changeState is delayed until the dmc.moveTo is complete.
(it may make more sense to factor this stuff out into separate methods rather than using the Runnable-in-a-Runnable anonymous classes)