I'm building a game in Android, and I have two threads. One for my data, and one for my UI. Up to this point, it's been fairly straightforward, as the UI thread pulls data that updates from the main thread without a problem. The issue I'm running into, is that my UI thread pauses certain parts of the game(a countdown timer) while it runs a certain animation, and I need a way to start that countdown timer again in the data thread, once the animation has ended. I have some solutions I've been working up, but it all seems so convoluted.
Is there something like a listener or something evens simpler where I can indicate to my data thread that a specific animation has ended in my UI thread? I just can't seem to get it to work the way I want.
Here's a pseudo code version of what I'm doing:
Main
{
gamethread();
UIthread:
while(gameIsRunning)
{
UIthread.draw();
if(gamethread.startAnimationButtonIsPressed)
{
UIthread.startAnimation;
}
}
}
Basically, in this pseudo code example, I'd need a way to indicate to the gamethread to unpress the startanimation button, or toggle that boolean or whatever.
Related
I have an AnimationTimer, that I use as an infinite loop like this:
animator = new AnimationTimer(){
#Override
public void handle(long now) {
// Update
Game.simulationStep();
// Render
Game.render();
}
}
};
animator.start();
The handle function is called 60 times a second, updates a small Game and renders some views in a scenegraph.
What I´m asking myself is, if when I have Events like a button click, will the code of the event be executed after a loop iteration is done?
Or is it multithreaded?
The thing is, I have a List of GameObjects which can be manipulated by the event (removing GameObjects by button click) but also by the logic in simulationStep.
It could be problematic, if the event removes GameObjects from that List, while simulationStep() is doing something with the Objects in the List.
The answer depends not on the code you provide but on your other code.
If the code is responding to events originating in the JavaFX framework (like a button press), then you don't need to worry, because those events are also on the JavaFX thread, the same as the animation timer.
You only need to worry if the event originates on a different thread outside of JavaFX. For example, an incoming chat message from a network chat client, or an AI loop that you are running on your own thread.
Also, you shouldn't use property listeners and bindings that might change values on another thread. For example, don't modify from another thread an observable list that is used to back a list view. The internal implementation of the observer and binding features assumes that the properties and listeners are all used on a single thread. Again, that is only something to worry about if your code is actually multi-threaded.
If you do really have multi-threaded code with events originating from other threads, use JavaFX concurrency, e.g. Task and/or Platform.runLater. Possibly in conjunction with a queue as in Seph's answer as demonstrated (somewhat), by this multi-threaded JavaFX logging framework using a queue. However, usually a separate queue is not required, because Platform.runLater will add runnables to a built-in queue that JavaFX maintains for stuff to be run on the JavaFX thread later.
For your specific concern:
I have a List of GameObjects which can be manipulated by the event (removing GameObjects by button click) but also by the logic in simulationStep. It could be problematic, if the event removes GameObjects from that List, while simulationStep() is doing something with the Objects in the List.
No. It will not be problematic. Everything is running on a single thread, the GameObjects cannot be removed by button click while simulationStep() is running, because the click handler and the simulationStep cannot be running at the same time.
A good summary of different options for executing periodic events and when and when not to involve multiple threads, plus how to handle them if they are used, is in Slaw's answer to:
JavaFX periodic background task
I advise reading the JavaFX architecture overview sections on the Glass Windowing Toolkit, Threads, and Pulse (twice). The document explains how the JavaFX system works with respect to threading, event processing, and pulse handling (the AnimationTimer handle method is triggered by a pulse).
AnimationTimer is not multithreaded and the handle() method runs on the JavaFX application thread, so I guess if you put an infinite loop or a blocking call inside handle(), it freezes the application. Answering your question, unless you have some behaviour that executes on other threads, it'll work fine.
Here's a related thread: Is AnimationTimer running in its own thread?
You can add the events to a queue and process that queue first in your animation timer. This should avoid anytime of concurrency or race condition issues you may be concerned about without hurting anything if they do not actually exist.
animator = new AnimationTimer(){
#Override
public void handle(long now) {
//Process
Game.processEvents();
// Update
Game.simulationStep();
// Render
Game.render();
}
}
};
animator.start();
On devices running Android 2.2, I want to detect when the user has pressed the screen for a certain length of time. Imagine sending a morse code message, with short taps (dots) and longer presses (dashes). I want to react to short taps as soon as the user lifts her finger, and to longer presses after (say) 500 milliseconds, even if she continues to hold her finger down.
I've looked at both FutureTask and ScheduledExecutorService but these look like overkill for this implementation. Or perhaps I just have cold feet about dealing directly with threads, and seeing all the code that is needed to handle them.
Here's simplified pseudo-code for how I have done this sort of thing in other languages:
public boolean onTouch(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
timer = createObjectToCallback(callbackMethod, 500); // milliseconds
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (timer still exists) {
timer.kill();
// Do the short press thing
} else {
// Do nothing. It already happened when callbackMethod was triggered
}
}
}
public void callbackMethod() {
// Do the long press thing. The timer has already auto-destructed.
}
What simple ways are there of doing this in Java?
== EDIT in response to the answer from #zapl ==
Writing code that works is one thing. Understanding how it works is another.
If I understand correctly, the thread that updates the UI is already running in a loop. Let's imagine a very simple case.
The Main activity creates a black canvas, and contains an onTouch method. When it starts, it calls setOnTouchListener. The Main thread now listens constantly to input from the screen. If the way the user is touching the screen has changed, it calls the onTouch method, with information about the change.
Let's say that the onTouch method draws a green circle around the touch point. This circle is drawn using cycles belonging to the Main thread. When the drawing is finished, the Main thread starts checking for new changes from the screen. If there are no changes, then onTouch is not called again, and the green dot does not move.
When the user lifts her finger, the screen provides changed information to the Main thread, and the code in the onTouch method erases the dot.
Create interface
Has the screen detected a change? No: loop
Has the screen detected a change? No: loop
...
Has the screen detected a change? Yes: draw a green dot; loop
Has the screen detected a change? No: loop.
...
Has the screen detected a change? Yes: new position => redraw the green dot; loop
...
Has the screen detected a change? Yes: not touching => remove dot; loop
Has the screen detected a change? ...
Suppose that I want the dot to turn red if the user's finger does not move for at least 500 ms. No move means no callback to onTouch. So I can set up a Handler, which adds itself to the loop in the Main thread. The Main thread now has two actions in its loop.
Create interface
Has the screen detected a change? No: loop
Has the screen detected a change? No: loop
...
Has the screen detected a change? Yes: a touch; draw a green dot; add Handler; loop
Has the screen detected a change? No;
Is it time for Handler to trigger? No: loop.
...
Has the screen detected a change? No;
Is it time for Handler to trigger? Yes: change dot color to red; remove Handler; loop.
Has the screen detected a change? No: loop.
...
Has the screen detected a change? Yes: not touching => remove dot; loop
Has the screen detected a change? ...
Any code executed by the Handler will block the Main thread until it has completed.
Is that an accurate description of what Handler does?
Using threads when you actually don't need parallelism is indeed way overkill because it adds it's own set of problems. What you need is to schedule code that runs in the future, but on the same thread. Android's Handler can do exactly that. You can either schedule a Runnable or a Message to arrive. There is also the derived CountDownTimer for simpler scheduling of periodic events.
But it's probably not required in this case because there is the GestureDetector.
It comes with Android and can distinguish between several types of single, long and double taps. It also behaves consistent with the rest of the system. You will probably want to use that.
More about that http://developer.android.com/training/gestures/detector.html
If you really want to implement your own or just to see an example of how to use a Handler, have a look at GestureDetector's source . It's full of code like the one you've posted (mHandler.hasMessages, mHandler.removeMessages, mHandler.sendEmptyMessageDelayed).
Note: Handler is not standard Java class because scheduling events in the same thread requires a thread to be message queue based and there is no standard solution for that. It's also UI framework dependent how threadsafe the framework is. Android's tries to throw exceptions if you even try to modify the ui from some background thread. The same aproach should however work with Swing's Event Dispatch Thread (SwingUtilities.invokeLater) for example.
Edit: trying to explain Ui thread & handler:
Any code executed by the Handler will block the Main thread until it has completed.
correct. Android's main thread works very simplified like this:
public BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
public void loop() {
while (true) {
Runnable currentTask = queue.take(); // blocks until something happens
currentTask.run();
// repeat.
}
}
public void enqueue(Runnable runnable) {
queue.put(runnable);
}
public static void main(String[] args) {
startThreadsThatReceiveSystemEvents();
enqueue(new Runnable() {
#Override
public void run() {
Activity activity = createStartActivity();
activity.onCreate();
activity.onResume();
}
});
loop(); // fun fact: an android app will never return from here
// it's process is simply killed by the system
}
The real world equivalent is often found in stacktraces pretty far down:
E/AndroidRuntime(20941): at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime(20941): at android.app.ActivityThread.main(ActivityThread.jav a:3691)
Everything that Android does in terms of starting / stopping Activites, drawing the screen, .. is the result of something getting enqueued so that the run loop evaluates it at some point. A Handler uses the very same queue. And everything you enqueue will be executed interspersed with all the other things that already happen withing that loop. One thread can't do things parallel to itself so it's all sequential. This is why Handler tasks block other tasks.
Your example with touch events is basically correct, it's just not actively looking at the touchscreen. It is getting notified via it's connection to the system. There is essentially another thread (the Binder threads in case you have ever looked at the list of threads) listening for messages from the system and once they arrive, all this thread needs to do is to enqueue them for the main loop. This can automatically wake the loop up if it was waiting.
The main thread queue is actually not a simple BlockingQueue since it needs to support scheduled events as well. It's an android specific implementation called MessageQueue and is partially implemented in native code. The loop method is in it's own class as well (Looper). And the queue isn't using Runnable directly, it's actually a queue of Messages - which can contain a Runnable (in a hidden field) and the run loop when it finds a Runnable in a Message will just execute it like in above sample code.
Each Handler is bound to one Looper/MessageQueue combination (and therefore to 1 thread). Handler.post/sendMessage does the dirty work of constructing a proper message & enqueueing it. The Message has a link back to your Handler so the loop know's which Handler's handleMessage method to call.
Besides using the already existing main thread loop/queue, you're free to create additional queue based threads and Handlers for those. https://stackoverflow.com/a/13369215/995891 contains a tiny example for that.
I'm trying to make "Realtime Feeling JTable". I made GUI with JTable, and then there is a button named START. When I click this button, the program will call below start() method. (It's just an example). Adding row is no problem, It works well. But the problem is, rows come to Jtable just at one time. (maybe program finish start() method, The rows come up with at all together.) There is 1000 more statement in my start() method. It's not realtime feeling. I shoud wait until start method finished. and then 1000 rows added at once.
void start(){
int a = 3+3;
addRow(new String[]{"a is 6"})
int b = 4+4;
addRow(new String[]{"b is 8 "})
}
What I'm gonna do is just "Real Time Feeling", I want to see adding row one by one, not at once. Could you understand my purpose? Imagine "Fiddler" Program. you can understand easily. Can anyone help me? Should I make a Thread?
Thanks for reading, and sorry for ackward expression(english is not my language)
This is because of the way Swing threading works. There is one single thread that handles all rendering, updating, etc. Your processing of the start() method is happening inside that render thread so nothing else on the GUI will respond until you return from the method.
What you need to do is use a SwingWorker or a ThreadPoolExecutor and farm the processing off to another thread. That can then update the GUI on a regular basis as the processing continues.
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
Note that by doing this people can potentially click the button multiple times and call start() again before the first one has finished. You will need to consider and handle that case - for example by disabling the button until the first one completes.
Use a Swing based Timer. In the actionPerformed(..) add a new record. See How to Use Swing Timers for details.
In swing there is a thread called EDT (Event Dispatcher Thread) that is responsible for GUI to behave like a real time, user friednly app. If you interfer EDT with a long running method you will freeze your app GUI. You have to do long running tasks in background (in a thread different than EDT). You can do this by using javax.swing.SwingWorker<T,V> or javax.swing.Timer
I'm making an Android game, and I'll need a continuously running thread for basically everything.
Now, however, I'm making the main menu (I always start simple, I'm new to coding), and I want an image to float across the main screen. I know how I could code that (determining the starting location, changing it), but I don't know how to run such a piece of code continuously (outside the UI thread).
P.S.: Please be easy on me. I know I'm probably missing something obvious, but I have virtually no Java experience at all.
1. Create a Non-UI thread, with Handler. And run it within Controlled loop using a boolean variable. Handler will be helpful in putting the output of the Non-Ui thread on the
Ui thread.
2. You can use an AsyncTask, introduced in android to synchronize the UI with Non-Ui thread.
while(check){//your code}
In run method you can put put a globle boolean variable to check the condition.
After having some trouble with setting up a thread to start my MIDI sequencer I decided to simply remove it, although it would slow my UI down I would be able to use it correctly.
What I noticed however was that even when playing the Sequencer the UI was very much active, even if it was playing around 500 notes the UI worked perfectly fine.
Now I know that in C# if you are doing something intensive it is advisable to load it on a new Thread as it will free the UI. Is it the same principle in Java, it's really confused me. If so can someone explain how the UI is not being blocked?
Thanks
Edit:
The following code actually plays the Sequence
public static boolean Play() {
if(!_sequencer.isRunning()) {
try {
_sequencer.setSequence(_sequence);
_sequencer.start();
return true;
} catch (Exception e) {
Logger.Add(e.getMessage());
}
}
return false;
//Already running
}
Yes, it is the same theory. Only the Event Thread can modify the UI, and thus if you are doing anything on that thread, then you are preventing other events from working on the UI.
It may be easier to think about the Event Thread as a queue:
Show Form
Click Button
Do your work (Action)
Reset focus of Button
Update Progress Bar
Et cetera
If #3 takes long, then it may mean that your form will appear locked up. Obviously it completely depends on your definition of long. In general, it's better to work off of the Event Thread rather than on it.
It's definitely the same principal. Generally speaking you want to only do minimal work with the UI thread. If it ends up taking any significant time, it can cause the UI to be unresponsive and you can get a "Not Responding" error. You want to keep the UI thread as free as possible so it can respond to user interaction.
If your application has a graphical user interface, it's advised that you perform expensive calculations on a new Thread to keep your graphics from freezing. You can either create a SwingWorker, or use the Callable/Future idiom.
Yes, you're right. Read Threads and Swing for more info.