I'm starting to study threads and I don't understand why the following simple code does not work. It is throwing:
RuntimeException: can't create handler inside thread that has not called looper.prepare():
Here's the code
public void onClick(View v) {
switch (v.getId()) {
case R.id.id1:
Thread th =new Thread(new Runnable() {
public void run() {
update();
delObjects();
addObjects();
}
});
th.start();
break;
}
}
I have read that sometimes the error occurs when you try to modify the UI, but it's not my case.
Thanks in advance!
If you are not accessing the UI stuff, then the chances are you are doing deep threading. Basically you cannot start a thread from unside a run() method which is already threaded. So your methods,
update();
delObjects();
addObjects();
might be using threading and which causes this issue. In most cases, you don't need such threading since you are already outside the UI thread and so you can skip to have threading inside these functions. In some cases if these functions has to be used somewhere else where no wrapper thread is running, you might need to have threads in the methods itself. So if that is the case, change your code as the following.
public void onClick(View v) {
switch (v.getId()) {
case R.id.id1:
Thread th = new Thread(new Runnable() {
public void run() {
//Prepare for further threading.
Looper.prepare();
update();
delObjects();
addObjects();
}
});
th.start();
break;
}
}
Hope that helps.
When you create the thread, you use var name "th", but when you start the thread, you use "th1". Is this a typo when you ask question, or it's error in your code?
Related
I'm writing an application using JavaFX and my understanding is that, while the UI runs in a thread, all other non-UI operations must run in another. So far, all examples I've found are variations of the following:
myButton.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent a) {
// Some UI operations
new Thread() {
public void run() {
// Some non-UI operations
Platform.runLater(new Runnable() {
public void run() {
// Some operations to update the UI
}
});
}
}.start();
}
});
My question is: do you need to somehow kill the thread in order to release its resources? In the examples I've never nobody seems to use Thread.join or any other similar method.
Also, would it be advisable to use setDaemon like this?
myButton.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent a) {
// Some UI operations
final Thread child = new Thread() {
public void run() {
// Some non-UI operations
Platform.runLater(new Runnable() {
public void run() {
// Some operations to update the UI
}
});
}
};
child.setDaemon(true);
child.start();
}
});
Note:
According to this thread (JavaFX multithreading - joining threads won't update the UI) Thread.join must not be used, but it doesn't seem to address the question of what happens to the threads that are no longer needed or how to kill them.
Threads will age out when there is nothing scheduled for them. However, it is not a good practice to depend on that, as it can take up resources.
The better approach is to use an ExecutorService, such as described in the documentation. A ThreadPoolExecutor can run one or more threads. You can use the same executor to keep submitting runnable tasks, and they will be executed on the threads that it manages. The documentation gives examples on how to shut down the executor service at the end of your application. If you are confident that you have no outstanding tasks being executed, you can issue shutdownNow() to immediately clean up all the threads.
I'm programming a thread that when 10 seconds have passed since beginning it execution it will make visible one component of the UI:
The code is the following:
Thread buttonThread=null; // this is a global variable
[...]
buttonThread = new Thread()
{
#Override
public void run()
{
try
{
super.run();
sleep(10000); //Delay of 10 seconds
} catch (Exception e)
{
}
finally
{
try
{
buttonThread.suspend();
cont.setVisibility(View.VISIBLE);
buttonThread.destroy();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
};
buttonThread.start();
But when I try to execute the buttonThread.suspend() I'm getting a java.lang.UnsupportedOperation exception.
I'm aware that using suspend is unsafe, and that's the reason it's deprecated, but I'd like to check first that suspending the thread does work and doing it by calling .suspend() looks the easiest way.
Could you, please, suggest me some possible solution so the thread shown in the code is suspended?
I'm programming a thread that when 10 seconds have passed since beginning it execution it will make visible one component of the UI:
The thread is overkill here and its use its not justified. Use plain Runnable and post it with required delay (postDelayed()) instead - that would more than enough for your task.
There is plenty of ways of doing something like this in android. The most common one being, using a Handler class like this.
add this import line.
import android.os.Handler;
and use this code to create a new runnable using handler class.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// do your stuff here
}
}, DELAY_IN_MILLI_SECONDS);
I need to call the same thread multiple times in my app. Using my original code, the first time is can be executed just fine. But the second time it crashes - I then learned that each thread shall only be executed not more than one time.
My original piece of code:
View.OnClickListener myClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
mythread.start();
}
};
Thread mythread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
So as I said, it crashes if I try to run it for the second time. So I tried modifying it like:
View.OnClickListener myClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
test();
}
};
private void test(){
Thread mythread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
mythread.start();
}
It works very good; but my question is that whether this is the correct way to do this action or there is a more optimal way to do this?
Also, is it an acceptable thing to call a thread from insider of another thread? (like the way I put stuff on UI Thread inside the new thread of mine)
EDIT:
This is just an example. For my actual code I have heavy math-based simulation to be done which takes 10sec to be done. Based on the results that will be shown to the user , they may want to change their input parameters and let the simulation run again. This will happen several times.
In addition to the other good answers about using AsyncTask or runOnUiThread(), you could define a private member as a Runnable, like this:
private Runnable mytask = new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
Then, whenever you want to run it, do
new Thread(mytask).start();
There is nothing bad with that but I think a better way would be using AsyncTask. It is exactly designed for this cases.
You can use AsyncTask multiple times just creating a new one like this new MyAsyncTask().execute(""); (source from here)
Also, is it an acceptable thing to call a thread from insider of another thread? (like the way I put stuff on UI Thread inside the new thread of mine)
runOnUiThread exists solely for that purpose. But there are usually much better ways (e.g. AsyncTask) so using this method is probably a bad idea.
my question is that whether this is the correct way to do this action or there is a more optimal way to do this?
You should not use a thread just to schedule future tasks. They are useful to execute something in parallel to the main thread but add lots of potential errors (try rotating the screen between it prints running..finished, could crash)
I would use a CountDownTimer in your case.
Or a Handler, examples e.g. here: Schedule task in android
From the provided code I assume that you want to perform an UI operation before and after your long mathematical computation. In such as #Andres suggested, AsyncTask is your best buy. It provides method onPreExecute, onPostExecute which runs on UI thread, and thus no need for explicitly calling runOnUiThread.
Key concepts :
You can't start an already started thread. This will return in an IllegalStateException. If you need to perform same task again, you should create a new instance.
If you find yourself creating several instances of a thread (even AsyncTask), since you need to run same task again and again, I would suggest you to use Thread Pool or simple Java Executor Service. Create a singleThread or may be pool and post your runnable onto executorService and it will take care of the rest.
Inter-Thread or Inter-Process communication is quite common requirement.
I'm starting a thread which loops indefinitely until a certain event occurs. The problem is, I want to start this thread, and then return to the normal execution of my program. However, after starting the thread, the code seems to get stuck.
Code:
public void init()
{
Runnable thread = new Runnable()
{
public void run()
{
while(something)
{
//do something
}
}
};
System.out.println("Starting thread..");
new Thread(thread).run();
System.out.println("Returning");
return;
}
When I start this, I get the output "Starting thread" but I don't get "returning" until the conditions for the while loop in the run() stop being true.
Any ideas how I can make it work asynchronously?
Use start rather than run to start a Thread. The latter just invokes the run method synchronously
new Thread(thread).start();
Read: Defining and Starting a Thread
You may try this in your code:-
new Thread(thread).start();
like:-
public void init()
{
Runnable thread = new Runnable()
{
public void run()
{
while(something)
{
//do something
}
}
};
System.out.println("Starting thread..");
new Thread(thread).start(); //use start() instead of run()
System.out.println("Returning");
return;
}
You want to call new Thread(thread).start() instead of run().
Are you sure about your approach? You say:
The thread should loop indefinitely until certain event occurs.
that's an enormous loss of computational resource, the program is principally bound to get slow & fail. You may want to put the thread in wait() mode and catch InterruptedException to wake it up upon occurrence of your event of interest. If this preliminary understanding of what you are trying to accomplish is true then Id' strongly suggest you to revise your approach. Computing resource is expensive, don't waste it in relentless looping.
I have a java code that looks like this:
//UI thread
//Some code
Job j = new Job(jobName) {
#Override
public IStatus run(IProgressMonitor monitor) {
try {
//Some code
SomeFunc();
//Some code
return Status.OK_STATUS;
} catch(Exception e) {
}
finally {
}
}
};
j.schedule();
The problem is that the SomeFunc(); must be called from the UI thread.
I'm new to java, so can you please help me with showing the best methods for posting event to UI thread or calling a function of UI thread?
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
// your UI code
}
});
or you can use SwingWorker, its another choice:
http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
In SWT, use Display.syncExec() as in this snippet or Display.asyncExec().
Its worth having a look at the Eclipse Jobs and Background Processing tutorial by Lars Vogel. There are good examples on how to run code on the UI thread from Eclipse Jobs.