A thread:
public class DrawThread extends Thread {
private RMapCanvas canvas;
final Handler myHandler = new Handler();
final ArrayList<RGroupMapLayer> layers;
public DrawThread(RMapCanvas aCanvas, ArrayList<RGroupMapLayer> arrayOfLayers)
{
canvas = aCanvas;
layers = arrayOfLayers;
}
public void run() {
activity.RaiseNotification(activity.getApplicationContext().getResources().getString(R.string.loading).toString());
for (RGroupMapLayer l : layers)
{
l.validateAndRepairView(false, canvas.renderer, canvas.mapView);
l.render(canvas.renderer, canvas.mapView, canvas.mapEvent, 5000000, 5000000);
if (settings.getPositionFeature() != null)
{
RPointFeatureStyle positionStyle = new RPointFeatureStyle(RPointFeatureStyle.SIMPLE_POINT_STYLE_GPS);
positionStyle.render(settings.getPositionFeature(), renderer, mapView);
}
myHandler.post(new Runnable() {
#Override
public void run() {
canvas.RenderComplete();
}});
}
activity.statusMessage.cancel();
}
public synchronized void requestStop() {
activity.statusMessage.cancel();
this.interrupt();
}
}
Calling the requestStop that interrupts a thread is not enough. The thread just keeps running. Can some one please update the code to show me the correct way of stopping this thread? And by the way ... the RenderComplete() methods updates the UI (witch is a problem in my case, because "old" threads keep updating the UI even if new one is starter and the old one interrupted).
Thanx in advance.
In general interrupting or stoping threads by yourself is not recommended. Your thread should have a flag inside the run method. When the flag is true - the thread is running, when the flag is false - thread is also running, but now it doesn't do anything. The system will stop this thread when needed. Here's how it should look:
public void run() {
while (flag) {
//do your work
}
}
And to "stop" the thread just use flag = false;
Hope this helps.
Related
I have the following method, that called every time I click over a button, this results to start a new thread again and again when the button is pressed, that results to multiple initialisation of thread, however I want only one thread should get executed, how can I achieve this.
private void scheduleMessages() {
new Thread(new Runnable() {
#Override
public void run() {
//Some operations
}
}).start();
}
Note: this is a small method and I don't want to create a separate class, just to make it singleton, so a solution without singleton pattern will be appreciated.
if you cannot make instance of this to check isActive() you should make a semaphore variable - a boolean, that you set to true when you start thread and set to false when you are done.
private void scheduleMessages() {
if (!taskRunning){
new Thread(new Runnable() {
#Override
public void run() {
taskRunning = true;
//Some operations
taskRunning = false;
}
}).start();
}
}
Have that thread be a background thread - maybe initialize it when the button is pressed the first time.
Have that thread listen to a queue - and act upon messages in that queue.
Whenever the button is pressed again, put a new message into the queue.
If your need to execute every requests but on a specific number of threads, you can use a thread pool and let the executor manage the queue .
private ExecutorService services;
private final static int POOL_SIZE = 1;
public MessagesService(){
services = Executors.newFixedThreadPool(POOL_SIZE);
}
public void scheduleMessages(Runnable r){
services.submit(r);
}
If you call addCall x times, x thread will be executed at the end but will never use more than the number of thread available in the pool. Here, 1 thread.
For a system that only accept one request, you can use the same approch but check the Future returned by a single thread executor. That way, you can check the status of the service.
private ExecutorService services;
private Future<?> lastCall;
public MessagesService() {
services = Executors.newSingleThreadExecutor();
lastCall = null;
}
public synchronized void scheduleMessages(Runnable r) {
if(!isScheduled()){
lastCall = services.submit(r);
}
}
public boolean isScheduled(){
return lastCall != null && !lastCall.isDone();
}
That way, the Runnable doesn't need to update a flag, which give a reusable solution.
Here is a sample of the Runnable to test these codes :
new Runnable() {
System.out.println("Running");
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
Is there a way I can do a similar task like the android OS or java AWT thread where a task is run on a particular thread regardless of which thread of which thread the method was called from e.g. repaint().
private Thread thread;
public void startThread(){ //method which start's my thread
thread = new Thread(new Runnable(){
doSomething();
});
thread.start()
}
public void submitTask(Runnable runnable){
//run the runnable task on the thread "thread"
}
How can I achieve something like this, on a situation where I have more then one active thread
How I've dealt with this scenario before is to create a work queue and a thread which processes tasks that get added to it. So any thread can add a work item to the queue and the same thread will process it regardless of what thread added the work item.
public class MyClass {
private LinkedBlockingQueue<MyTask> myTaskProcessingQueue;
public MyClass() {
myTaskProcessingQueue = new LinkedBlockingQueue<MyTask>();
new MyTaskWorker().start();
}
public void processTask(MyTask myTask) {
myTaskProcessingQueue.put(myTask);
}
private class MyTaskWorker extends Thread {
#Override
public void run() {
while (true) {
try {
processMyTask(myTaskProcessingQueue.take());
} catch (InterruptedException ie) {
// handle it
}
}
}
private void processMyTask(MyTask myTask) {
// do work
}
}
}
I have a simple Question:
I have a Thread named rlMF. I created it this way:
public Thread rlMF = new Thread(new Runnable() {
public void run() {
reloadMissingFiles();
stopTh();
}
public void stopTh() {
activityStopped = true;
}
});
Now i want to call the stopTh Function from outer Thread. Why can't i simply call rlMF.stopTh(); and what can i do else?
Example:
protected void onPause() {
Log.d("Info", "destroying...");
activityStopped = true;
rlMF.stopTh();
super.onPause();
}
Is not working...
Because the interface accessible is from Thread. In order to have you method accessible from out, you need to specify a type that exposes this method.
And if you take a look carefully the method is implemented in the instance of Runnable. Not even in Thread.
You could have something like this if you really need to access the Runnable object:
class MyRunnable implements Runnable {
public void run() {
...
}
public void fooBar() {
...
}
}
public void someMethod() {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
...
myRunnable.fooBar();
...
}
An example for Francisco approach, besides what you are trying to achieve. Maybe this can point you in the right direction
public class CustomRun implements Runnable {
public void run() {
reloadMissingFiles();
stopTh();
}
public void stopTh() {
activityStopped = true;
}
}
In your Code
// start thread with custom runner
CustomRun runner = new CustomRun();
new Thread(runner).start();
// call your stopTh method on CustomRun class
protected void onPause() {
Log.d("Info", "destroying...");
activityStopped = true;
runner.stopTh();
super.onPause();
}
Your goal is to interrupt the thread from onPause. There are several ways to do it, but essentially, you will need to include some interruptibility in reloadMissingFiles.
Option 1
You can use a boolean flag like you did - you need to declare it as volatile to make sure the changes are visible across threads:
private volatile boolean activityStopped = false;
public void reloadMissingFiles() {
while (!activityStopped) {
//load small chunks so that the activityStopped flag is checked regularly
}
}
public Thread rlMF = new Thread(new Runnable() {
public void run() {
reloadMissingFiles(); //will exit soon after activityStopped has been set to false
}
});
protected void onPause() {
//This will stop the thread fairly soon if the while loop in
//reloadMissingFiles is fast enough
activityStopped = true;
super.onPause();
}
Option 2 (better approach)
I don't know what you do in reloadMissingFiles, but I suppose it is some sort of I/O operations, which are generally interruptible. You can then have an interruption policy where you stop as soon as an InterruptedException is caught:
public void reloadMissingFiles() {
try {
//use I/O methods that can be interrupted
} catch (InterruptedException e) {
//cleanup specific stuff (for example undo the operation you started
//if you don't have time to complete it
//then let the finally block clean the mess
} finally {
//cleanup (close the files, database connection or whatever needs to be cleaned
}
}
public Thread rlMF = new Thread(new Runnable() {
public void run() {
reloadMissingFiles(); //will exit when interrupted
}
});
protected void onPause() {
runner.interrupt(); //sends an interruption signal to the I/O operations
super.onPause();
}
Note: you can also read this article for a more in depth version of it.
So I have the following thread:
public class MyThread extends Thread
{
Handler cHandler;
private boolean looprunning = false;
MyThread() {
cHandler = new Handler();
looprunning = true;
}
#Override
public void run(){
while (looprunning) {
//do stuff here
//update another system here or something else.
}
}
}
Inside the while loop of this thread, I want to run a Runnable that I pass to the thread while the thread is looping inside that while loop. How do I do this?
first please mark looprunning as volatile for proper thread visibility
you can use a queue
Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<Runnable>();
#Override
public void run(){
while (looprunning) {
//do stuff here
//update another system here or something else.
Runnable r = taskQueue.poll();
if(r!=null)r.run();
}
}
you can use a (thread-safe) queue of your choice
Android already provides a mechanism for creating threads that run in loops that execute Runnables. Have a look at HandlerThread
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;
}
}