In Android we have Handler#post(Runnable) method to post some code to the main thread from another
Is it possible to make same thing in plain java (for instance while using swing)?
Explaining the question:
Assume we have two threads: ThreadA and ThreadB. Both are started already and running side-by-side. And ThreadB wants ThreadA to invoke some method (again, ThreadA is already running).
Addition optional question (you may not answer it):
And if it's possible, someone explain me how does exactly Handler do in Android. How it's able to post some code to MainThread? What is a purpose of the Looper?
Addressing your additional question:
You said "In Android we have Handler#post(Runnable) method to post some code to the main thread from another"
It is not exactly correct. You can 'post some code' from any thread A to any thread B provided that thread B is initialized as a Looper and the thread A has a reference to a Handler for the target thread B.
It is very convenient when you need to do something on the UI thread because the UI thread already has a Looper and you can retrieve it from nearly everywhere. The static method Looper.getMainLooper is a way to get a Looper for the main thread. If you initialize a Handler with this Looper you can post a Runnable or send a Message to it (though if you post Runnable it also gets wrapped into a Message) and it will be executed on the UI thread.
Looper, as the name hints, is basically running a non-terminating loop for a thread. The Looper has an associated MessageQueue which it constantly checks for new Messages. Via the Handler initialized with a Looper you can enqueue Messages on this thread. The Messages are processed in a sequential order, depending on the when field of a Message.
Here's a basic implementation of a Looper thread:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
I suggest you read the Chapter 5 of Meike G.B. Android Concurrency. It will give you a comprehensive insight into the Looper/Handler framework. It is also great to browse the source code while you are reading, it is rather simple and self-explanatory.
Within Swing you would use
https://docs.oracle.com/javase/8/docs/api/javax/swing/SwingUtilities.html#invokeLater-java.lang.Runnable-
to run something on the main thread.
In general Java, an ExecutorService is like a thread pool and allows you to submit Runnable or Callable instances
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
However, if you aren't using an ExecutorService or Swing, there is no standard Java API to tell another thread to do something.
Related
I have read on stack this:
When you use new Handler().post(r) (or Message), you added the
Runnable object to Looper and execute the code later in the same
thread.
this answer is accepted.
So now I have a dilemma, some guys on my last interview give me tip: if you want to run something in other thread and update from this new thread UI, lets use a Handler.
So Handler is new thread or not ?
Or maybe runnable in this thread works on other thread ?
Can somebody explain me ?
from official doc:
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed at some point in the future; and (2) to
enqueue an action to be performed on a different thread than your own.
Handler is not a new thread. It is just a mechanism to schedule some task to be done in the UI thread.
Creating/Posting to a Handler does not create new thread.
The Runnable posted to a Handler runs in the UI thread as soon as UI thread becomes free.
When you create a Runnable instance and post it, its reference gets stored and its run method will be called from the UI thread, at some point in the future. (You can also specify the delay using the method postDelayed().)
A Handler is associated with a Looper (and that Looper's thread). When you call new Handler() to create a new handler you're associating it with the Looper for the current thread (the thread where the current code is running).
Once you have this object, you can use it from another thread to report results, etc.
So for example, from a background thread you can call post() on a handler object that is associated with the UI thread. The Runnable you pass will be executed by that handler in its thread (not in the thread where the post() function was called) when the Handler gets to it.
For another source of info/details on loopers and handlers see https://developer.android.com/training/multiple-threads/communicate-ui
Here's the quote form Android documentation:
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed at some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
This part is quite important:
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it
Handler is not a new thread and it can handle messages in a queue when you're passing new Runnables to the Looper thread, which process them. Each message can be processed in a separate thread or thread pool, when you explicitly do it. Otherwise, it will be processed in the thread, where Looper was created (it can be main/UI thread or other thread).
I was also confused about this mechanism some time ago, collected some links, resources and wrote sample app using Handler and Looper. You can check it here: https://github.com/pwittchen/android-looper-sample. Maybe you'll find it useful.
I am using the Unity game engine which also supports exporting to Android.
The engine uses multiple threads, including the UI thread and a separate scripting thread where all the user custom code is executing.
My scenario requires that i call some operation in a background thread, and i would like to marshal the result back to the main scripting thread.
I know the basics of the AsyncTask, Executor and Looper classes. Out of these, Looper seems like a good candidate since it allows setting up a queue and post back messages to a given thread (AsyncTask is "hardwired" to run the callback on the UI thread, which is not what i want here).
What is the proper way of achieving this?
There is 3 main ways to communicate with the UI thread :
Activity.runOnUiThread(Runnable)
View.post(Runnable)
Handlers
In your case, I advice you to create an Handler, as the 2 first solutions imply that you have a reference on your Activity or a View
Edit
If you want to use any thread in your app, just make sure a Looper has been set, and use an associated Handler
class YourLooperThread extends Thread
{
// make it accessible from the outside
private Handler handler;
#Override public void run()
{
Looper.prepare();
// Customize your handler, it has to be used in any thread which want to push a message in this thread's looper message Queue
handler = new Handler();
Looper.loop();
}
}
Be careful : all the other tasks you want to do in that thread must be done through the message queue, i.e posting a runnable in the handler. More information here : Handlers, MessageQueue, Looper, do they all run on the UI thread?
This question already has answers here:
Handler vs AsyncTask vs Thread [closed]
(13 answers)
Closed 8 years ago.
I know this Question has been asked many times but all answers I got wasn't clear for Me.
I want to implement a File deletion process. I discovered that to do this kind of work it's recommended to run all the process in a separated thread.
For that, I can use AsyncTask, Handler and Thread. AsyncTask seems to be a good solution. However, AsyncTask is designed for small task. (When i try to delete a file whose length is more than 1G, AsyncTask crashes or doesn't execute onPostExecute.
Others thread handlers (Thread, Runnable...) can't manage UI (Update UI or show progress).
My Question is What is the good thread handler for Long tasks and How to manage UI with it.
First of all, if you need to perform work outside your main thread, but only while the user is interacting with your app, then you should create a new thread, otherwise use a Service.
Now, everything you can do with AsyncTask, you can also do it with a Thread(+ Handler). But the AsyncTask makes the developer job easier, because it is designed to communicate a worker thread with the main thread(caller thread). Now, if you use a Hanlder you can also communicate a worker thread with a caller thread(Note that the caller thread is not necessarily the main thread, it could be communication between two worker threads), if the caller thread is the main thread, you better use AsyncTask.
As far as i know, it goes something like this:
Use AsyncTask if you need to run a short task communicating with the UI thread
Use a Thread and Handler to run longer tasks that requires communication between the worker thread and the main thread(caller thread)
Use Thread, Handler and Looper (or HandlerThread, which is class for starting a thread that already has a Looper) for longer tasks that require communication between the worker thread and the caller thread(not the main thread).
Use IntentService for longer task that does not requires user interaction and needs only one worker thread.
The best for me, is the Asynctask, because the structure is well defined, you can know when is running the thread and when show the result.
http://masl.cis.gvsu.edu/2010/04/05/android-code-sample-asynchronous-http-connections/
Good article on using handlers above.
To delete using handler:
Create a runnable that does three things:
Delete file
Obtain msg and send on success
Obtain msg and send on failure
Using some framework to manage threads or using concurrency package, post the runnable and it will do the file Del off main thread. Handler callback will be msg success or msg fail that will process on main thread wherview controller.
Check out Needle and you can forget Handlers and AsyncTasks. Needle is an open-source, simple but powerful multithreading library for Android. With it you can say things like:
Needle.onMainThread().execute(new Runnable() {
#Override
public void run() {
// e.g. change one of the views
}
});
or
Needle.onBackgroundThread().execute(new UiRelatedTask<Integer>() {
#Override
protected Integer doWork() {
int result = 1+2;
return result;
}
#Override
protected void thenDoUiRelatedWork(Integer result) {
mSomeTextView.setText("result: " + result);
}
});
very simple API
fixed thread pool size
customizable thread pool size
supports UI interaction ("do work and then use result on UI thread")
android 1.5+
behaves the same on all platform versions
Check it out on GitHub: https://github.com/ZsoltSafrany/needle
I have read that the main UI thread in android should not call sleep.
However, my application needs to :
call thread1 from main UI thread
call thread2 from main UI thread.
Use the output (2 images) of the 2 thread, add them and then display them.
I am using Thread.sleep() so that the main thread waits thread1 and thread2 till they are done. However mImageview.setbitmap is not working after i call it in the main thread (after sleep).
can u pls advise me how i should do this?
Multithreading in Android should be done Asynchronously. For this purpose, you should use the AsyncTask-class.
For your case, you would for example create a taks to load (or process) those two images. While the process is running (in another thread, off the UI-thread), you could show a ProgressBar that shows to the user that your application is currently busy (this is then done on the UI-thread).
When the task has finished, you get the results (your two images) from the task, hide the progress-bar and show everything to the user.
Despite the fact that a non-reacting GUI always has the feeling that your application frooze, if a UI-Thread is blocked for more then 5 seconds (which is a looong time), your application will be Force-closed as it is not "reacting" (and an ANR will be raised).
It's not just Thread.Sleep(). In the GUI thread, do whatever you need to to start the two threads/tasks/whatever and then exit the event handler.
Do not wait in GUI event-handlers! Not in Java, C++, C, Delphi, anything. Use an async task, or a Handler, and signal to the GUI thread. Thread 1 signals that it is done, thread 2 signals that it is done. In either case check to see if the data has been returned by the other thread. If it has, you have both sets of returned data and so you can add them and display them.
Do not wait in GUI event-handlers.
You can simply use Threads And Handlers for this purpose.
Here is a small demo for this,
Create a Handler in your onCreate like this,
Drawable d=null;
Handler handler=new Handler()
{
public void handleMesaage(Message msg)
{
if(msg.what==0)
{
imageView.setBackgroundDrawable(d);
}
}
};
And now call Your Thread like this,
Thread t=new Thread(new Runnable()
{
#Override
public void run() {
InputStream is = (InputStream) new URL(url).getContent();
d = Drawable.createFromStream(is, "src name");
handler.sendEmptyMessage(0);
}
});t.start();
I would suggest to use the ExecutorService. Here is how
Create the two image loading activities as Runnable tasks.
Execute them with the ExecutorService.
Use ExecutorService.awaitTermination(); for the main thread to wait for Runnable tasks to complete. Its documentation reads
Blocks until all tasks have completed execution after a shutdown
request, or the timeout occurs, or the current thread is interrupted,
whichever happens first.
This is the Asynch way of doing it and I guess should be preferred.
The following code leads to java.lang.IllegalThreadStateException: Thread already started when I called start() method second time in program.
updateUI.join();
if (!updateUI.isAlive())
updateUI.start();
This happens the second time updateUI.start() is called. I've stepped through it multiple times and the thread is called and completly runs to completion before hitting updateUI.start().
Calling updateUI.run() avoids the error but causes the thread to run in the UI thread (the calling thread, as mentioned in other posts on SO), which is not what I want.
Can a Thread be started only once? If so than what do I do if I want to run the thread again? This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
From the Java API Specification for the Thread.start method:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
Furthermore:
Throws:
IllegalThreadStateException - if the thread was already started.
So yes, a Thread can only be started once.
If so than what do I do if I want to
run the thread again?
If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.
Exactly right. From the documentation:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
In terms of what you can do for repeated computation, it seems as if you could use SwingUtilities invokeLater method. You are already experimenting with calling run() directly, meaning you're already thinking about using a Runnable rather than a raw Thread. Try using the invokeLater method on just the Runnable task and see if that fits your mental pattern a little better.
Here is the example from the documentation:
Runnable doHelloWorld = new Runnable() {
public void run() {
// Put your UI update computations in here.
// BTW - remember to restrict Swing calls to the AWT Event thread.
System.out.println("Hello World on " + Thread.currentThread());
}
};
SwingUtilities.invokeLater(doHelloWorld);
System.out.println("This might well be displayed before the other message.");
If you replace that println call with your computation, it might just be exactly what you need.
EDIT: following up on the comment, I hadn't noticed the Android tag in the original post. The equivalent to invokeLater in the Android work is Handler.post(Runnable). From its javadoc:
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* #param r The Runnable that will be executed.
*
* #return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
So, in the Android world, you can use the same example as above, replacing the Swingutilities.invokeLater with the appropriate post to a Handler.
No, we cannot start Thread again, doing so will throw runtimeException java.lang.IllegalThreadStateException.
>
The reason is once run() method is executed by Thread, it goes into dead state.
Let’s take an example-
Thinking of starting thread again and calling start() method on it (which internally is going to call run() method) for us is some what like asking dead man to wake up and run. As, after completing his life person goes to dead state.
public class MyClass implements Runnable{
#Override
public void run() {
System.out.println("in run() method, method completed.");
}
public static void main(String[] args) {
MyClass obj=new MyClass();
Thread thread1=new Thread(obj,"Thread-1");
thread1.start();
thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
}
}
/*OUTPUT in run() method, method completed. Exception in thread
"main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
*/
check this
The just-arrived answer covers why you shouldn't do what you're doing. Here are some options for solving your actual problem.
This particular thread is doing some
calculation in the background, if I
don't do it in the thread than it's
done in the UI thread and the user has
an unreasonably long wait.
Dump your own thread and use AsyncTask.
Or create a fresh thread when you need it.
Or set up your thread to operate off of a work queue (e.g., LinkedBlockingQueue) rather than restarting the thread.
What you should do is create a Runnable and wrap it with a new Thread each time you want to run the Runnable.
It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
It is as you said, a thread cannot be started more than once.
Straight from the horse's mouth: Java API Spec
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
If you need to re-run whatever is going on in your thread, you will have to create a new thread and run that.
To re-use a thread is illegal action in Java API.
However, you could wrap it into a runnable implement and re-run that instance again.
Yes we can't start already running thread.
It will throw IllegalThreadStateException at runtime - if the thread was already started.
What if you really need to Start thread:
Option 1 ) If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.
Can a Thread be started only once?
Yes. You can start it exactly once.
If so than what do I do if I want to run the thread again?This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
Don't run the Thread again. Instead create Runnable and post it on Handler of HandlerThread. You can submit multiple Runnable objects. If want to send data back to UI Thread, with-in your Runnable run() method, post a Message on Handler of UI Thread and process handleMessage
Refer to this post for example code:
Android: Toast in a thread
It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
I have had to fix a resource leak that was caused by a programmer who created a Thread but instead of start()ing it, he called the run()-method directly. So avoid it, unless you really really know what side effects it causes.
I don't know if it is good practice but when I let run() be called inside the run() method it throws no error and actually does exactly what I wanted.
I know it is not starting a thread again, but maybe this comes in handy for you.
public void run() {
LifeCycleComponent lifeCycleComponent = new LifeCycleComponent();
try {
NetworkState firstState = lifeCycleComponent.getCurrentNetworkState();
Thread.sleep(5000);
if (firstState != lifeCycleComponent.getCurrentNetworkState()) {
System.out.println("{There was a NetworkState change!}");
run();
} else {
run();
}
} catch (SocketException | InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Thread checkingNetworkStates = new Thread(new LifeCycleComponent());
checkingNetworkStates.start();
}
Hope this helps, even if it is just a little.
Cheers