I'm trying to create a simple thread that started from a Button but something went wrong.
Here is the code:
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
SendInfo si = new SendInfo();
si.start();
error.setText(si.getError());
}
});
And here is the the thread code:
package com.example.android.location;
public class SendInfo extends Thread
{
private String error;
public void run()
{
this.error = "working";
}
public String getError(){
return this.error;
}
}
For some reason the error instance in the first code block stays empty.
You have a race.
After the start() call either:
1) your code continues and getError returns null and AFTER that the thread runs.
or
2) the thread runs AND finishes and getErrorwill return "working".
In your case 1) is happening.
Update: actually in theory during option 2 you might not get "working" anyway as the return value. This is due to memory/thread visibility. Synchronizing access to the error variable or in this case just declaring that field volatile fixes that (but not your original problem).
You should better use ASyncTask than Thread.
There's no guarantee that the thread started after this line
si.start();
so you can't just get error in hope that it's set as expected. Your thread didn't by the looks of it.
Also, it would be wise to synchronize on the method, to prevent nasty reordering of instructions.
One solution to this problem as a whole, is to create a handler on main thread and send a message to it once your thread completes execution.
Related
i have an Android App published in the Play Store, and the crashreports show a Fatal Exception: java.lang.IllegalThreadStateException: Thread already started
in
public void refresh(){
if (Thread.currentThread() != mThread) {
mThread = new Thread() {
#Override
public void run() {
refresh();
}
};
mThread.start();//<<<<<<<<<<<<<here
return;
}
doSomeCoolStuff();
}
how can this happen? it is a new thread?
Metin Kale
This can happen in case of a race condition. Between the two statements (assigning a value to mThread and calling the start() method), the execution can switch to another thread, which can enter the refresh() method again, assign a different thread to mThread, and then start it. When the first thread resumes execution, mThread will contain a different thread (which has already been started), and the start() method will fail with the exception that you describe.
One way to fix this is to store the result of new Thread() in a local variable, then call the start() method on that variable, and then save it into the field. (This may not be the most appropriate fix, but it's not possible to say more without knowing more details about the context where the problem happens.)
Probably your mThread is already started and running, thats why do you get that exception.
Try to check the state of mThread, and start it only when is in Thread.State.NEW state.
if (mThread.getState() == Thread.State.NEW)
{
mThread.start();
}
Thread.State.NEW: The thread has been created, but has never been started.
I've a method who return a result (return an integer), my method is executed in a Thread for load 40 000 objects, i return an integer who count the number objects loaded. My question is, How return the int with the Thread ? Actually, the result is returned directly and is equal to 0.
public int ajouter(params) throws DaoException, ConnectException {
final ProgressDialog dialog = ProgressDialog.show(mActivity, "Title",
"Message", true);
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dialog.dismiss();
}
};
Thread t = new Thread() {
public void run() {
try {
Str_Requete = "SELECT * FROM Mytable";
ResultSet result = ExecuteQuery(Str_Base, Str_Requete);
Index = addObjects(result);
handler.sendEmptyMessage(0);
} catch (SQLException e) {
e.printStackTrace();
}
}
};
t.start();
return Index;
}
When i call my method in my mainActivity :
int test = myObjs.ajouter(params);
test is equal to 0, the value is returned directly...
My constraint is didnt use AsyncTask.
The whole point of using a Thread is not to block the calling code while performing the task of the thread. Thread.start() returns immediately, but in the meantime a new thread is started in parallel to the current thread which will execute the code in the run() method.
So by definition there is no such thing as returning a value from a thread execution. You have to somehow send a signal back from the thread that performed the task to the thread in which you need the result. There are many ways of doing this, there's the standard Java wait/notify methods, there is the Java concurrency library etc.
Since this is Android, and I assume your calling code is running on the main thread, it's probably wise to use the functionality of Handler. And in fact, you are already doing that - you have a Handler that closes the dialog when the thread is done with its work - but for some reason you seem to expect the result of that work to be ready before it has even started. It would be reasonable to extend your existing Handler with some code that does something with the calculated value and remove the code that returns the value of a variable before or at the same time as it's being calculated by another thread.
I also strongly encourage you to study some concurrency tutorial such as Oracle's concurrency lesson or Android Thread guidelines to really understand what's going on in the background. Writing concurrent code without mastering the concepts is bound to fail sooner or later, because it's in the nature of concurrency that multiple things are happening at the same time, will finish in random order etc. It may not fail often, but you will go crazy wondering why something that works 90% of the time suddenly fails. That's why topics such as atomicity, thread synchronization etc are critical to comprehend.
Edit: Simple Android example of starting a worker thread, performing some work, posting back event to main thread.
public class MyActivity extends Activity {
private Handler mHandler = new Handler();
...
private void doSomeWorkInBackground() {
new Thread() {
public void run() {
// do slow work, this may be blocking
mHandler.post(new Runnable() {
public void run() {
// this code will run on main thread,
// updating your UI or whatever you need.
// Hence, code here must NOT be blocking.
}
});
}
}.start();
// This code will be executed immediately on the main thread, and main thread will not be blocked
}
You could in this example also use Activity.runOnUiThread(Runnable).
Please consider however that AsyncTask basically wraps this kind of functionality in a very convenient way, so if it suits your purposes you should consider using AsyncTask.
If you dont want to use AsyncTask or ForkJoin, then you could implement an Interface e.g. callback in your main class.
In your Example you dont wait until the Thread is done... thread.join
One Solution:
Your Thread is a extra class with an constructor to hold the reference to the calling class.
public Interface callback
{
public int done();
}
public class main implements callback
{
...
CustomThread t = new CustomThread(this)
...
}
public class CustomThread extends Thread
{
private Callback cb;
public CustomThread(Callback cb)
{
this.cb=cb;
}
.
.
.
//when done
cb.done(int)
}
I have a Singleton in an Android App (which works just fine) in one of the functions I need to set data in a class variable in another thread but the data only sets if I run the function twice.
onCreate:
Thread thread;
Runnable runnables;
String recvData;
#Override
public void onCreate() {
super.onCreate();
singleInstance = this;
recvData = "one";
Log.v("oncreate", "singleton");
}
threaded_data_set:
public String threaded_set_data() {
runnables = new Runnable(){
#Override
public void run() {
recvData = "two";
return;
}
};
thread = new Thread(runnables);
thread.start()
Log.v("Data", recvData);
return recvData;
}
on the first run it logs ("Data", "one") and only on the second one it changes to ("Data", "two")
What am I doing wrong here?
The default values of recvData is:
recvData = "one";
nothing is wrong here, the
Log.v("Data", recvData);
just printed out before your thread prints out the second log message.
You are assuming the thread has finished as soon as you get to the logging statement.
Try logging the value in the thread as you set it as well, you'll see that code happens after your first logging call.
It is working right but you're expecting the thread to finish before your method moves on is all :)
Not much is going wrong here, you just aren't using the new assignment value for recvData
public String threaded_set_data()
{
runnables = new Runnable(){
#Override
public void run() {
recvData = "two";
Log.v("Data", recvData);
//return; <-- not really needed
}
};
thread = new Thread(runnables);
thread.start()
Log.v("Data", recvData);
return recvData;
}
At the first run of the thread, the latter is running in it's own thread which means that you're already returning recvData before the runnable finishes running since it's running in parallel. What you would want to do is use an AsyncTask instead.
You're seem to missing the nuances of how threads work. I think you are assuming that your threads runs and returns before your log statement, however you can't safely assume that.
Instead, try using a handler like the comment in your question. A handler is designed exactly for this type of thing. Vogella (a fantastic resource btw) does a much better job of explaining it so I will direct you there.
Okay I'm sure I'm missing something simple here but can't see it. I'm using a flag to end a thread and then joining it to clean up neatly, but the join never finishes it just gets stuck waiting. There is currently nothing in the thread's run loop so it isn't getting stuck in a separate loop.
Thread:
package com.nox.willywars;
public class GameThread extends Thread {
//{{Variables
private boolean running;
//}}
//{{Getters/Setters
public void setRunning(boolean running) {
this.running = running;
}
//}}
//{{Constructor
public GameThread() {
running = false;
}
//}}Constructor
//{{Public methods
#Override
public void run() {
while(running) {
///...CODE GO HERE
}
}
public boolean isRunning() {
return running;
}
//}}
}
Code that fails to stop it:
//{{Lifecycle methods
#Override
public void create() {
//LOAD! Probably debug temp
TileFactory.load();
mapScreen = new MapScreen();
setScreen(mapScreen);
gameThread = new GameThread();
gameThread.setRunning(true);
gameThread.start();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
killGameThread();
}
private void killGameThread() {
if(gameThread != null) {
if(gameThread.isAlive() && gameThread.isRunning()) {
gameThread.setRunning(false);
boolean retry = true;
while(retry) {
try {
gameThread.interrupt();
gameThread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
gameThread = null;
}
}
//}}
Currently it reaches gameThread.join() and gets stuck there, waiting for the thread to finish. Am I missing something here? As I understand the thread should finish once running is set to false and then joining should happen normally because it's already stopped.
Edit: Added some more code from the class that runs GameThread. Pause() is where KillGameThread is executed. I've made running volatile but it's had no effect.
I found another weird symptom too: Some people suggested looking at what's inside GameThread when it's stuck, so I went into the debugger. While join() is stuck I suspended the GameThread thread and saw it was on while(running), and running was definitely false. Then when I stepped over the code it exited the loop and finished correctly, seemingly caused by my debugging. It's as if the thread is somehow suspended?
first set the running flag as volatile
private volatile boolean running;
What does game thread do exactly, maybe it has blocked by some I/O operation.
and if the game thread doesn't sleep/wait/join, so interrupting it is useless.
you need to share the game thread code.
As user2511414 pointed out, try with using volatile. In short, this will make sure the value od running is always accessed directly and not cached.
It setting volatile won't solve the situation, he problem most probably lays in the code section of a GameThread#run method that you commented out.
You can try using jstack or jvisualvm to get a Thread Dump of the thread you're trying to join.
This will at least show you where is it hanging, and may lead you to a solution.
The running flag is not properly synchronised. This could (in theory) result in the thread not noticing the state change ... due to the way that the Java memory model works. You should either declare it as volatile or always access and update it in synchronized method calls (or synchronized blocks).
But (IMO) the real problem is in the way (actually the ways) that you are telling the thread to stop, and haw the thread is checking or responding.
If you are going to use a flag to tell the thread to stop, then the thread needs to check that flag frequently. If the thread could spend an indefinitely long amount of time doing something else between the checks, then it may never notice that it needs to stop.
If you are going to use Thread.interrupt() then:
Your code should be calling Thread.isInterrupted() to test the thread's "interrupted" status instead of an ad-hoc flag. Furthermore, it should be testing the status regularly.
Your code need to make sure that it handles the InterruptedException and InterruptedIOException properly. This applies all the way up the call stack.
Note that calling Thread.interrupt() doesn't actually interrupt the thread in most cases. In most cases, it just sets a flag that needs to be tested manually. The only cases you get more than that is in certain blocking calls; e.g. Object.wait(...) and some IO calls.
You've left out most of the code where these things ought to happen. The best we can say is that the problem is most likely in code you haven't shown us.
I didn't fully understand the concept of threads I have some questions. Assume we have the following code:
ExecCommand.java
// I don't know how this work, for now
package therads;
// Here we will have the methods and run them from the Main.java
public class ExecCommand implements Runnable
{
String name;
int time;
public ExecCommand(String s,int amount)
{
name = s;
time = amount;
}
// Run method (Runnable)
public void run()
{
try
{
// What to execute when the thread is started
System.out.printf("%s is sleeping for %d\n",name,time);
Thread.sleep(time);
System.out.printf("%s is done\n",name);
}
catch(Exception e)
{
}
}
// This dosen't work when the thread is stopped
public void stop()
{
try
{
System.out.printf("STOPPED!");
}
catch(Exception e)
{
}
}
// This dosen't work when the thread is started
public void start()
{
try
{
System.out.printf("Started!");
}
catch(Exception e)
{
}
}
}
and i call him from :
Main.java
Thread t5 = new Thread(new ExecCommand("Good Function",1000));
t5.start();
I want to println() "Started" when the thread is started and "Stopped" when it finished. It is possible?
When a thread is completed, it dies, complete released from memory? If not, how i can do that?
How can i make a thread that repeat itself like once every 1000 miliseconds till i press a key? I was thinking about while(true) { t5.start; }
but i don't know for sure.
First of all, there is no point in using the start and stop methods. Everything happens in the run method.
To print a message on start and stop, put them at the start and end of the run method. To loop indefinitely and keep executing code until an outside event happens, use a flag and loop on it:
class ThreadTask implements Runnable {
private volatile boolean flag = false;
public void setFlag(boolean value) {
flag = value;
}
public void run() {
System.out.println("Started");
while(!flag) {
// execute code
}
System.out.println("Stopped");
}
}
Then when you want the thread to stop, just set the flag to true using setFlag.
And yes, threads are automatically cleaned up by the runtime + OS after the run method terminates.
Why or when would you expect your .start() and .stop() to be called? Runnable has only a single method in the interface; .run(). The JavaDocs for Thread cover it pretty well. http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html. If you want something to happen when your Thread starts, put that something at the top of your .run(). If you want something to happen when your Thread is finishing, put it at the bottom of the .run(). By-in-large doing anything with the .start() and .stop() methods on Thread is discouraged. Concentrate on doing all you lifecycle stuff within your .run(). And get a copy of "Java Concurrency in Practice" by Goetz. It will show you the full range of your options (including don't do you own Threading directly).
You are not supposed to override the start and stop methods. They are not callback methods.
What you want is something akin to the SwingWorker class (assuming you are interested in UI related threading synchronization).
If not, you can subclass Thread yourself and provide a callback mechanism.
Yes of course. You can just print "Started" in the first line of your run() method, and print "Stopped" either in a finally section of run() method or just after t5.join()
You are not told about the details, and cannot do anything. But you can assume the resources are freed as soon as necessary. (Of course if you have reachable links for any references allocated within your thread, JVM cannot decide that these are of no use, so "complete" is not a proper word here.)
Take a look at java.util.Timer
If you prefer to use System.out.println instead of printf just change those lines of code. There's nothing thread-related about those calls.
The thread will be collected and released from memory by the garbage collector when it has stopped running and there are no live references to it. Same as all objects.
Don't override stop(). This has been deprecated and should really be dealt with by the JVM, not your application code. Just override run to implement whatever you want your thread to do, as per the docs
You can use Thread.sleep to sleep for a period of time. How accurate the sleep will be will depend on your platform and the resolution of the available system clock.