Hello i'm new in Android(Java), and i have a problem with the use of thread
I define e new Thread timed (every 5 seconds) inside a class of my android Project.
The "mContinueThread" variable is used to cicle every 5 seconds
r = new Runnable() {
public void run() {
while (mContinueThread) {
try {
Thread.sleep(MILLISEC_BEFORE_RELOAD);
mHandler.sendEmptyMessage(GET_TRACKING);
}
catch (Exception e)
{
}
}
}
};
t = new Thread(r);
In the CLass there is a method StartTrack() that starts with Thread
public void StartTrack()
{
mContinueThread=true;
if (!mThreadIsStarted)
{
mThreadIsStarted=true;
t.start();
}
else
{
}
}
and there is also a method Logout that stop the thread, using the "mContinueThread" variable:
public void LogOut()
{
//STOP THREAD
mContinueThread=false;
....
}
If in the class Logout() method is executed the thread is stopped, but if the StartTrack() method is called again I don't know how to restart the execution of the thread.
Can you Help Me?
You can use AsyncTask in Android. This will get rid of the burden of managing the threads manually. Please visit http://developer.android.com/reference/android/os/AsyncTask.html
You cannot re-start a thread. Once thread is finished execution it will reach the DEAD state. And whatever is DEAD cannot be brought back to life again, neither in real world nor in JAVA world.
You have no way to restart a thread as long as it exited. You can just start a new start.
I solved so:
In my class I just define the Runnable object, but not the new Thread.
In the StartTrack method(), if the thread has not yet been instantiated, I create and start
public void StartTrack()
{
mContinueThread=true;
if (!mThreadIsStarted)
{
mThreadIsStarted=true;
t = new Thread(r);
t.start();
}
}
In the "LogOut()" method, if Thread is started, I Stop It, and I set It to Null.
In this way, at the next call of "StartTrack()" method, I can recreate it again
public void LogOut()
{
mContinueThread=false;
if (mThreadIsStarted)
{
//THREAD STOP
mContinueThread=false;
mThreadIsStarted=false;
//THREAD TO NULL
t=null;
}
...
}
I suggest it's better to use something like Timer instead of thread.
http://developer.android.com/reference/java/util/Timer.html
Then you can do cancel() if you want to stop execution of your task
and resume it by scheduling new one.
Related
I am dealing with threads and I want to run this code whenever I open Cal_JInternalFrame. It runs the fist time, but whenever I reopen the frame, it doesn't run again. I use t1.interrupted() at exit time of the whole application. The code is:
Thread t1 = new Thread( new Runnable() {
#Override
public void run() {
while ( !t1.isInterrupted() ) {
// ......... Oil Calculation Thread ...
int price = (Integer.parseInt(jLabel22.getText()));
int qty = (Integer)jSpinner8.getValue();
int totalOil =qty * price;
jTextField19.setText(String.valueOf(totalOil));
}
}
});
t1.start() is in the constructor of the main frame.
The thread primitive methods destroy(), stop(), resume(), and suspend() have been deprecated, so I can't use those. How can I stop and resume a thread now? And if my thread t1 is interrupted, how can it be resumed or run again?
Threads cannot be re-used. For tasks that require to be executed on a separate thread at different times, use a single thread executor.
It seems like you need a worker thread. Since standard threads are not reusable without extra work, we use worker threads to manage tasks that should be executed multiple times.
ExecutorService executors = Executors.newSingleThreadExecutor();
With this, you can reuse a single thread to execute code multiple times. It also allows you to make asynchronous callbacks using Future like this:
class Demo {
static ExecutorService executor = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
Future<String> result = executor.submit(new Callable<String>() {
public String call() {
//do something
return "Task Complete";
}
});
try {
System.out.println(result.get()); //get() blocks until call() returns with its value
}catch(Exception e) {
e.printStackTrace();
}
}
}
You can now re-use executor for the task that you want. It accepts Runnable through it's execute(Runnable) method.
I see you're using Swing. Post all swing code to the Event Dispatch Thread using EventQueue.invokeLater(Runnable). getText() and setText() should be called on the Event Dispatch Thread to avoid inconsistancies.
How can I stop and resume a thread now?
You can't. Instead, you need to make your thread stop and resume itself. For example:
private boolean wake;
public synchronized void wakeup() {
this.wake = true;
this.notify();
}
public void run() {
while ( !t1.isInterrupted() ) {
// do stuff ...
wake = false;
synchronized (this) {
while (!wake) {
try {
this.wait();
} catch (InterruptedException ex) {
t1.interrupt(); // reset the interrupted flag
}
}
}
}
}
When some other thread wants to get this one to do something, the calls the wakeup() method on the extended runnable object.
And if my thread t1 is interrupted, how can it be resumed or run again?
As you have written it, No. Once the thread returns from the run() method call, it cannot be restarted. You would need to create and start a brand new Thread.
However, what you are trying to do is unsafe. As #Erwin points out, it is not safe for the t1 thread to be calling methods on Swing objects such as jTextField19. You should only call methods on Swing objects from the Swing event dispatching thread.
Reference:
Concurrency in Swing
I have an Android app with a main tab activity, and several activities within the individual tabs. In my main activity's onCreate(), I have a runnable that creates a list, and in the individual activities, I make use of this list.
In the individual activities's onCreate(), I also have Runnables that operate on the list. However, I need these Runnables to only run when the main tab activity's Runnable completes creating the list, otherwise I'd get a null list. I'm trying to find an elegant way of doing this. Right now, in my main activity's Runnable, I'm setting a global boolean variable isDone, and in my individual activity's Runnable, I'm waiting for isDone to be set via a while loop. This works, but probably isn't the best way of doing so.
Any thoughts?
Thanks.
Edit:
I'm trying the following code out, but I'm getting runtime errors:
In my MainActivity's Runnable:
mainRunnable = new Runnable() {
public void run() {
try {
generateList();
synchronized(this) {
listDone = true;
notifyAll();
}
} catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
}
};
Thread thread = new Thread(null, mainRunnable, "Background");
thread.start();
In my OtherActivity's Runnable:
otherRunnable = new Runnable() {
public void run() {
synchronized(MainActivity.mainRunnable) {
if (!MainActivity.getListDone()) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
}
};
Thread thread = new Thread(null, otherRunnable, "Background");
thread.start();
The mainRunnable seems to run completely, but the otherRunnable seems to cause the app to crash. I get the following error message:
01-10 15:41:25.543: E/WindowManager(7074): Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#40539850 that was originally added here
01-10 15:41:25.543: E/WindowManager(7074): android.view.WindowLeaked: Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#40539850 that was originally added here
You can use the wait and notify methods.
To do this, there needs to be some globally accessible object whose lock isn't used by anything else in the program at this point in time. I'm assuming that the list-creating Runnable itself can play this role.
So you could add something like this to the list-creating Runnable class:
private boolean listsDone = false;
boolean getListsDone() {
return listsDone;
}
And something like this to its run() method, immediately after it's done creating the lists:
synchronized (this) {
listsDone = true;
notifyAll();
}
And something like this to the other Runnables' run() methods, at the point where they need to wait:
synchronized (listCreatingRunnableObject) {
if (!listCreatingRunnableObject.getListsDone()) {
try {
listCreatingRunnableObject.wait();
} catch (InterruptedException e) {
// handle it somehow
}
}
}
Update: To clarify, both synchronized blocks need to be synchronized over the same object, and you have to call wait() and notifyAll() on that object. If the object is the Runnable, then it can be implicit for the first one (as in the above code), but if it's the activity, you need to explicitly use the activity object in both cases.
You can use a Queue like this:
public class RunQueue implemements Runnable
{
private List<Runnable> list = new ArrayList<Runnable>();
public void queue(Runnable task)
{
list.add(task);
}
public void run()
{
while(list.size() > 0)
{
Runnable task = list.get(0);
list.remove(0);
task.run();
}
}
}
This allows you to use one thread rather than multiple threads. And you can maintain all your existing "Runnable" objects while simultaneously cleaning up any code they have for waits and joins.
Set up a CountDownLatch with a value of 1 in the main thread, then have the dependent threads wait on it. When the main thread is done, you Count Down the latch to 0 and the waiters will start right up.
An active wait using a while loop is not a good idea at all. The simplest thing would be for the first Runnable to just fire up the rest of them as its last step. If that can't be made to work for some reason, take a look at posting a message to a Handler.
Is there a reason you are using Runnables and not Threads? If you use Threads, you can use the various thread communication primitives which exist for this exact reason (wait() and join() in particular).
I have created a helper method that contains all the boilerplate code for posting a runnable and waiting until it finishes running.
The logic is similar to what #Taymon describes, but the implementation is more general.
Check it out:
https://gist.github.com/Petrakeas/ce745536d8cbae0f0761
Maybe you can refer to Looper in Android. Simply, a thead keep running task from queue in a while loop.
Code:
public void doSomethingOrThrowUncheckedException()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
myObject.doSomething()
} catch(CheckedException e) {
new UncheckedException ();
}
}
});
worker.start();
}
Explanation
I want to perform some work in another thread that can throw a checked exception.
I cannot wait for this work to finish and I want the method caller to know if something went wrong with this work since the new thread is not able to handle the exception properly.
Is there a mechanism I can use?
Can you create a Observable outside of the thread? If something goes wrong, the thread sets a value to change that Observable. The main code is an Observer and reacts to the change when the property listener is called.
It depends on what you mean by the caller knowing that something went wrong. A couple of options come to mind immediately.
The worker thread can set an error flag. The disadvantage is that the calling thread will need to check the flag to know that something went wrong. (There can also be a flag for success; as long as neither is set, the calling thread knows that the worker is still working.
The worker thread can call an error method. The disadvantage is that the call will take place in the worker thread. On the other hand, this provides a place to take positive action. The Observer pattern might be useful here (although I think Java's implementation is terrible).
If, when the worker thread completes successfully it communicates the success to Foo, or produces an object that Foo consumes, then expand that mechanism to allow it to pass the checked exception along to Foo, rather than passing the exception to the method calling thread.
public void doSomething()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
result = myObject.doSomething();
foo.processResult(result);
} catch(CheckedException e) {
foo.processException(e);
}
}
});
worker.start();
}
public void doSomething()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
result = myObject.doSomething();
resultQueue.add(result);
} catch(CheckedException e) {
resultQueue.add(e);
}
}
});
worker.start();
}
If doSomething() doesn't interact with anything when it successfully completes then you'll need to follow one of the other answers.
You may also want to have a look at uncaughtExceptionhandler.
I have a daemon thread which is started when a page is opened. The thread is then stopped when the page is closed. So in my class which holds the thread, I have it created like this:
class A {
private static volatile boolean isStopped=false;
//this method is called then the page is loaded
public void testListener() {
Thread listener = new Thread(new Runnable() {
public void run() {
while(!isStopped) {
//perform listener event
try {
//after every event sleep for a while
Thread.sleep(1000 *2)
} catch(InterruptedException e){}
}
}
});
}
listener.setName("Test-Server-Daemon");
listener.setDaemon(true);
listener.start();
// reset back to false so thread can be restarted when the page load event,
// call this method instance
if (isStopped) {
isStopped=false;
}
}
/**This is called when page is closed**/
public static void stopListener() {
isStopped=true;
}
}
Upon investigation, I have noticed that when the page is closed and not opened again within say 30 seconds interval, the thread is gracefully stopped.
But when the page is closed and re-opened within say 2 seconds interval the old thread does not get stopped and hence runs simultaneously with a new one.
And so as you can see from below image, I have the same thread started again when I close and quickly open the page.
Do anyone knows how to prevent this from occurring?
I have tried using thread interrupt where I reset the mutex but no joy.
EDITED:
isStopped is volatile.
To follow on from #Jordão's answer, the isStopped variable should be per thread. I would recommend using something like an AtomicBoolean and changing your thread code to be approximately:
public AtomicBoolean testListener() {
final AtomicBoolean isStopped = new AtomicBoolean(false);
Thread listener = new Thread(new Runnable() {
public void run() {
while(!isStopped.get()) {
...
}
}
});
listener.setName("Test-Server-Daemon");
listener.setDaemon(true);
listener.start();
return isStopped;
}
Then back in your page controller you can do:
AtomicBoolean isStopped = testListener();
// do the page stuff
...
// when done stop the thread
isStopped.set(true);
You're probably overriding the value of isStopped with false before the old thread has a chance to see that it should stop. The problem is here:
if(isStopped)
{
isStopped=false;
}
You should better isolate your code: create separate instances of A for each thread and make isStopped an instance volatile field (not static). And remove that block of code...
If your flag isStopped is not true for at least 2 seconds, your thread could be sleeping when this happens. A much simpler solution is to avoid start/stopping the thread as this could cause as much overhead as it saves (it certainly complicates the issue)
This is what I would do is start the thread once and only once.
public void run() {
try {
while(true) {
if(!isStopped) {
//perform listener event
}
//after every event sleep for a while
Thread.sleep(1000 *2);
}
} catch(InterruptedException e){}
}
By setting the flag, it stops performing, but the thread keeps checking.
Try using AtomicBoolean instead of the Boolean field.
Use the compareAndSet method; let me know if u need more clarification as the javadocs are quite useful.
Try making isStopped volatile, i.e. private static volatile boolean isStopped=false;. There may be a lag in memory synchronization between the two threads (the main one and your own).
Move your instantiation outside of your method and make it static. This guarentee's you will only ever have one instance of this Thread.
private static Thread listener;
Once this is done you can add this to you're method:
if(listener.isAlive()) try { Thread.sleep(100); } catch (InterruptedException ie) {}
listener = new Thread(new Runnable() {
public void run() {
while(!isStopped) {
//perform listener event
try {
//after every event sleep for a while
Thread.sleep(1000 *2)
}
catch(InterruptedException e){}
}
}
});
Now you won't start a new thread until the previous one has stopped.
(NB, not sure if isAlive() is accurate, you may need to create your own Thread implementation to accurately reflect if the thread is stopped if it isn't)
I would used a java.util.concurrent.ScheduledExecutorService for that. It will manage the thread and the scheduling of the task.
For instance:
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Scheduler {
static ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
static ScheduledFuture<?> future;
// called when the page is opened
public static void open() {
future = service.scheduleAtFixedRate(new Runnable() {
public void run() {
//perform listener event
}
}, 0, 2, TimeUnit.SECONDS); // every 2 seconds
}
// called when the page is closed
public static void close() {
// stop listener event
future.cancel(true);
future = null;
}
}
I have a main form with a button, that when pressed, should start a new count-down timer thread.
This is the code in the button's action listener:
Counter c = new Counter(timeToFinish);
This is the code for the Counter class:
class Counter implements Runnable {
int waitingTime = 0;
Thread myCounter = new Thread(this);
public Counter(int waitingTime)
{
this.waitingTime = waitingTime;
myCounter.run();
}
public void run(){
//Start countdown:
do
{
waitingTime -= 1;
try {
Thread.sleep(1000);
System.out.println(waitingTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (waitingTime >= 0);
}
}
The problem is, when I create a new instance of the Counter class, it pauses the whole program, not just that thread! The problem must be with "Thread.sleep".
Because you are directly calling the run method.
Instead you should wrap it in a Thread and start the thread.
For e.g., replace
myCounter.run();
by
new Thread(this).start();
Just because you call the run method from the Counter constructor. That's not how it works with threads. You'll have to remove this call, wrap the Runnable in a Thread instance and call start() on the thread:
new Thread(new Counter(2)).start();
You aren't actually start()ing multiple threads.
The Thread.run() method simply runs the code associated with the thread, like any other normal function. It doesn't start a separate thread.
You need to call Thread.start(), to start a new thread and run your code in it.
You should use start() method of your thread. Use
c.start();
otherwise you have a class and you are invoking one of its methods, and of course it is running in main thread and sleeping the main thread.
You're calling run directly, it'll run in the current thread, and sleep the current thread, which I guess is the event thread. This cause the pause in your program.
You should use SwingUtilities class
see
http://www.java2s.com/Code/Java/Threads/InvokeExampleSwingandthread.htm
// Report the result using invokeLater().
SwingUtilities.invokeLater(new Runnable() {
public void run() {
resultLabel.setText("Ready");
setEnabled(true);
}
});
}
};