views:

346

answers:

5

i have set a thread and i want to run it using a loop. so this thread should run in the loop and break in a certain time and again run the loop.

please i have no clue how to do this. can someone guide me.

A: 

I can only give you some suggestion only. You can set a flag like isThreadRunning, and then when that flag is true, you run the loop, if it is not true, you out of the loop. About running the loop again, I think you can create a new thread for that. Here is some code snippet:

public class A extends Thread {
  public boolean isThreadRunning = true;
  public void run() {
    while(isThreadRunning) {
    // do task
    }    
  }
}

When a certain time happens, or another thread wants to stop that thread, you can just call A.isThreadRunning = false;

vodkhang
I think the one which you wrote is not a thread class.
RaviG
you artfully dodged concurrency issues - without appropriate synchronization or a volatile specifier, the thread may not even see the change to the flag
mdma
@RaviG: it is just a code snippet, and I expect the question guy knows how to create a class extends Thread, having run method.@mdma: how it doesn't see, if the other thread change the flag, in the next loop, that thread run into the while and it will see the that isThreadRunning is false, and it will stop the loop, right?
vodkhang
@vodkhang, no guarantee... the thread may see that the isThreadRunning flag is set or it may **never** see it was set. The variable can be cached thread-locally and unless you do something to **explicitly** updated the cached variable, then it may never be updated. Volatile ensures that the variable is never cached thread-locally, thus any changes are **always** visible to all the threads.
Lirik
Small note. I've learned that you should rarely extend Thread, and instead Runnable. Extending a Thread basically states that you have a specific implementation of a Thread, whereas extending a Runnable means that it can be run in a specific Thread.
Patrick
I agree, for me, extends thread means we also want to have some more methods from the superclass Thread.
vodkhang
A: 

Write your run method of your thread like this

public void run(){
   while (true){
       if (condition){
          // your logic
       }
       java.lang.Thread.sleep(1000L);
   }
}

In the above code, the loop is an infinite loop which will execute every second (1000 milli seconds) and your logic will be executed only if the condition satisfied.

If you want to increase the pause time to 2 seconds, change 1000L to 2000L

RaviG
thank you for the quick replies. appreciate them all. my thread is recognising a voice. this done using a speech recognition api. so i want my application to recognise everytime when a user say something. for this i do need have a loop and everytime it checks the voice input and output it to the certain functions. so my thread has this speech recognition. so do i have to loop the thread in my main class or can i loop just the speech recognition function and break and output anything by given time. like RaviG said execute every certain seconds.
Nubkadiya
No need to write a loop in main method. When you start the thread, using thread.start() method, your run method will be executed. In the while loop, you wan write what ever you wanted to execute.
RaviG
This is actually bad, you should instead use interrupting and `Thread.yield()` unless you really specifically want the current thread to completely idle for *about* the given time - `Thread.sleep()` doesn't guarantee that the current thread is going to wait for the specified time, it just tries to sleep the current thread for the specified time.
Esko
+6  A: 

Java has a built in mechanism for having a thread do something and then wait for a while to do it again, called Timer. You can put what would be inside your loop inside the Run() method of a TimerTask, and then tell the timer how often you want it done.

TimerTask task = new TimerTask() {
  @Override
  public void run() {
    //do some processing
  }
};

Timer timer = new Timer();
timer.schedule(task, 0l, 1000l); //call the run() method at 1 second intervals

It is of course your job to shut it down when the program is done.

http://java.sun.com/javase/6/docs/api/java/util/Timer.html

Affe
This is probably the easiest solution to get right. The executor solution by John W is perhaps a bit more mature.
Justin
Does this solution actually solve the OP's problem of breaking at a certain time?
CPerkins
+1 - I was also wondering if it solves the problem. But I guess it does if you call Timer.cancel() when you want the timer to stop.
mdma
Dunno! (if it's what he wants) That was how "Break in a certain time and run again" read to me, and he never came back to clarify, so we may never know.
Affe
+2  A: 

Assuming you're running on JDK 1.5 or newer (where memory model was clarified and improved) you can use

public class MyRunnable extends Runnable
{
   private volatile boolean quit;

   public void run() {
      while (!cancelled) { 
         doStuff();
      }
   }

   public void cancel()
   {
      cancelled = true;  
   }

   public boolean isCancelled() {
      return cancelled;
   }
}j

Alternatively, use java.util.concurrent.Future, and FutureTask, which supports cancellation out of the box.

mdma
Why do you need volatile for the quit variable? For this case, I think that is ok to not use volatile or synchronize there?
vodkhang
@mdma - you should use Thread.interrupt to do this kind of thing. For example, if `doStuff()` does a blocking wait or io call, then `interrupt()` will unblock it, but your approach won't.
Stephen C
I think it just depends on whether you really want to unblock it or just wait until it finishes getting io data and run to the next loop
vodkhang
@Stephen, you're right,in some cases using interrupt gets you what you want, especially if truly blocking i/o, e.g. socket reads or waiting for an event. There are at least 3 ways to code cancellable loops: volatile flag, synchronized flag, explicit interrupts and checks for isInterrupted, and using FutureTask, but rather than cloud the issue with too many examples, I thought it simplest to illustrate the general case and refer to FutureTask for other needs, which has a isCancelled flag and handles interrupts.
mdma
And then you need logic with a timer task to call cancel(), join on the thread, and restart the loop, yes?
CPerkins
@Vodkhang - you need either volatile or synchronized. If you don't have either of these, then the main executing thread may read the flag just once, and read each subsequent check of the flag from cache. Using volatile or synchronized ensures the cached value is ignored. Volatile is preferred in this simple case because it avoid synchronization overhead.
mdma
@CPerkins - perhaps - the OP is a little unclear on his eact needs - it's not clear if regular interruption/restart is needed or just a once/twice off, but they can be handled as Timers. Timers are discussed in the first answer so I elided repeating that.
mdma
@mdma - makes sense, just bears repeating somewhere close to the given answer.
CPerkins
+1  A: 

I feel we are missing the Executors!

There is an ScheduledExecutorService that you can use to run a task, then run again after a fixed amount of time. Its similar to the TimerTask but easier to manage and better maintained.

private final ScheduledExecutorService scheduler = 
                           Executors.newScheduledThreadPool(1);
 scheduler.scheduleAtFixedRate(new Runnable() {
            public void run() {
                //do work here  
            }
    }, 1, TimeUnit.SECONDS);

The Executor will scheudle this task every second and also can return a ScheduledFuture that you can use to either cancel or get result (if you are using a Callable instead of runnable).

Edit: CPerkins brings up a good point. How do we cancel after a certain amount of time then re execute. This is a bit much but it gets the job done I think.

    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final ExecutorService executor = Executors.newFixedThreadPool(1);

public void execute(){
    executor.submit(scheduleTask());
}
public Runnable scheduleTask(){
    return new Runnable() {
        public void run() {
            final ScheduledFuture cancel = scheduler.scheduleAtFixedRate(new Runnable() {
                public void run() {
                    // do work here
                }
            }, 0, 1, TimeUnit.SECONDS);
            scheduler.schedule(new Runnable() {
                public void run() {
                    cancel.cancel(true);
                    execute();
                }
            }, 1, TimeUnit.MINUTES);
        }
    };
}
John V.
No, It won't schedule it **every** second... Read the docs once again :)
BalusC
Ugh... I edited once to use the right api but didnt submit it! Thanks
John V.