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
}
}
}
Related
I have made a class called AbortableThread that is supposed to start and stop a thread when I want to. The class is relatively small since it just contains this code :
public class AbortableThread implements Runnable
{
private Thread worker;
private Runnable target;
public AbortableThread(Runnable target)
{
this.target = target;
}
public void start()
{
worker = new Thread(this);
worker.start();
}
public void stop()
{
worker.interrupt();
}
public void run()
{
while (!worker.isInterrupted())
target.run();
}
}
However, calling stop() does not stop the Thread. I think that's because target.run() runs on a separate thread, but I have no clue.
There isn’t a good way to stop a Runnable from outside (as a last resort there is stop, but that isn’t a good way).
A Runnable needs to be a good citizen and check for interruption itself, using Thread.currentThread().isInterrupted().
If the Runnable catches InterruptedException, the interrupt flag will be cleared; the Runnable needs to restore the interrupt flag by calling interrupt on the current thread.
In the posted code what happens is that the Runnable executes on the worker thread and the worker never gets a chance to check the interruption flag until the Runnable completes. Assuming the Runnable is something like
() -> { try {
Thread.sleep(100000L):
} catch (InterruptedException e) {}}
then the sleep would be cut short when the worker is interrupted, but the interrupt flag would be cleared so the Runnable would be executed again in the next iteration of the loop.
Try something like this:
public class AbortableThread implements Runnable
{
private final AtomicBoolean running = new AtomicBoolean(false);
private Thread worker;
private Runnable target;
public AbortableThread(Runnable target)
{
this.target = target;
}
public void start()
{
worker = new Thread(this);
worker.start();
}
public void stop()
{
running.set(false);
}
public void run()
{
running.set(true);
while (running.get()) {
try {
// make an small sleep
Thread.sleep(1);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"Thread was interrupted, Failed to complete operation");
}
// do something here like the one in question; it must be none-blocking
target.run();
}
}
}
A complete example can be found here:
How to Kill a Java Thread
I have these two methods for creating and stopping a thread. However the thread still keeps running, even after the first method is called. (I'm creating an object of the class and calling them from another class).
private Thread thread;
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
sendAlarm = false;
if (!thread.equals(null)) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void triggerAlarm() {
Runnable alarmTest = new Runnable() {
#Override
public void run() {
while (sendAlarm) {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
}
}
};
thread = new Thread(Test);
thread.start();
}
When stopAlarm is called the thread is always null, although it is called after triggerAlarm is called (thread is running).
Your problem is caused by thread scope. Thread scope is created when you create a thread with same variables in the scope but you can't change these variables from outside world. Best practice for managing runnables in android is to use Handler.
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
after definitions, in order to start the runnable:
handler.post(alarmTest,0); //wait 0 ms and run
in order to stop the runnable:
handler.removeCallbacks(alarmTest);
EDIT: wait statement with loop
EDIT: Complete solution
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
handler.removeCallbacks(alarmTest);
}
public void triggerAlarm() {
handler.post(alarmTest,0); //wait 0 ms and run
}
Depending on your OS you may find making your thread volatile may fix this.
private volatile Thread thread;
However - there are better ways to do this. One very useful one is using a small (just one entry) BlockingQueue which is polled by the running thread.
// Use a BlockingQueue to signal the alarm to stop.
BlockingQueue<String> stop = new ArrayBlockingQueue<>(1);
public void stopAlarm() {
stop.add("Stop");
}
public void triggerAlarm() {
new Thread(() -> {
try {
while (stop.poll(1, TimeUnit.SECONDS) == null) {
// Stuff
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Clearly you will have to manage edge cases like where someone calls stopAlarm when no alarm is running.
As I am using gui and I need to create a thread to complete a task. See I want to display a dialog letting the user know the task has been completed I have tried
if(!thread.isAlive()) {
JOptionPane.showMessageDialog(null, "Done");
}
But that doesnt work.
Can anyone help me
Thanks
One option is to do your work using a SwingWorker. Override the done() method and have it notify your GUI that work is complete.
A simple example that nearly matches your use case is shown in the Javadocs at the top of the page:
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
// Here you do the work of your thread
return findTheMeaningOfLife();
}
#Override
protected void done() {
// Here you notify the GUI
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
You could just have the thread print a message as it's last line of code in it's run method:
Thread thread = new Thread() {
#Override
public void run() {
//whatever you want this thread to do
//as the last line of code = the thread is going to terminate
JOptionPane.showMessageDialog(null, "Done");
}
}
thread.start();
If you want the main thread to wait for the thread to finish, in the main thread's code you'd use:
thread.join();
create a listener in your main Thread, and then program your Thread to tell the listener that it has completed.
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final Thread thread);
}
then create the following class:
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
#Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start(); // Start the Thread
then, as each Thread exits, your notifyOfThreadComplete method will be invoked with the Thread instance that just completed. So now you can run any of your code in this method.
Use Callable thread. It will return value,So we can identify that it completed its task.
i have one problem with handling the thread in android ,in my class i have to create one thread which create some UI after that thread finish i will get some value ,here i want to wait my Main Process until the thread complete it process but when i put wait() or notify in Main process thread does not show the UI in my application
this is sample code
protected void onCreate(Bundle savedInstanceState) {
downloadThread = new MyThread(this);
downloadThread.start();
synchronized(this){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String test=Recognition.gettemp();
public class MyThread extends Thread {
private Recognition recognition;
public MyThread(Recognition recognition) {
this.recognition = recognition;
// TODO Auto-generated constructor stub
}
#Override
public void run() {
synchronized(this)
{
handler.post(new MyRunnable());
}
notifyAll();
}
}
}
static public class MyRunnable implements Runnable {
public void run() {
settemp(template);
}
}
}
public static String gettemp() {
return template;
}
public static void settemp(String template) {
Recognition.template = template;
}
}
here i will not use AsynTask because i have some other issue that is reason i choose Thread even now the problem is Thread wait do any give the suggestion for this
- Use java.util.CountDownLatch , here you can let some process complete before kick-off some other code.
- countDown() and await() will be of use to you.......
See this example of CountDownLatch:
http://www.javamex.com/tutorials/threads/CountDownLatch.shtml
Use the logic below :-
new Thread(new Runnable()
{
#Override
public void run()
{
//do the code here such as sending request to server
runOnUiThread(new Runnable()
{
#Override
public void run()
{
//do here the code which interact with UI
}
});
}
}).start();
What do you expect to happen if you freeze the main UI thread?
You should be using an ASyncTask to show your gui in the onPreExecute method, do the task in doInBackground then display the result in the onPostExecute method.
As a plus you can update the progress using onProgressUpdate too.
This is not an solution just a advice on how should you structure you activity/app.
You should never block the main thread by calling wait() its a bad user experience and not advised. It would also case a Android Not Responding (ANR) popup.
You can have you thread updating the UI from the background and let the UI to be responsive. Load the static part of your UI in onCreate() and then fire up the background thread to lazy load rest of the component.
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.