What the best practice to run thread only for some period?
I can easily check curentTime and close the thread after in worked for some time, but I think it's not the right way.
It depends on what you want to achieve, but generally speaking the approach you mentioned with measuring the time from the start is not that wrong.
I would code it like this:
private static class MyTimerTask extends TimerTask {
private final Thread target;
public MyTimerTask(Thread target) { this.target = target; }
public void run() {
target.interrupt();
}
}
public void run() {
Thread final theThread = Thread.currentThread();
Timer timer = new Timer();
try {
timer.schedule(new MyTimerTask(theThread), 60000});
while(!theThread.interrupted()) {
....
}
} finally {
timer.cancel();
}
}
... which is Hovercraft described, except using interrupt instead of an ad-hoc flag. Using interrupts has the advantage that some I/O calls are unblocked by an interrupt, and some libraries will respect it.
I'm surprised (and deeply disappointed) that no one has mentioned the Executors framework. It has usurped the Timer framework (or at least the java.util.Timer class) as the "goto" for scheduled tasks.
For instance,
// Start thread
final Thread t = new Thread(new Runnable(){
#Override
public void run(){
while(!Thread.currentThread().isInterrupted()){
try{
// do stuff
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
}
});
t.start();
// Schedule task to terminate thread in 1 minute
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.schedule(new Runnable(){
#Override
public void run(){
t.interrupt();
}
}, 1, TimeUnit.MINUTES);
Related
I have a long running Runnable object and I wanted to provide a more graceful interrupt mechanism than having to call interrupt on the thread the object is running on.
The before code:
public class MyRunnable implements Runnable {
public void run() {
while(!Thread.currentThread().isInterrupted()) {
//do stuff
}
}
}
public class MyClass {
public static void main(String[] args) {
Runnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable, "myRunnableThread");
t.start();
//do stuff
t.interrupt();
//do stuff
}
}
And the new code:
public class MyRunnable implements Runnable {
private Thread myThread = null;
public void run() {
myThread = Thread.currentThread();
while(!myThread.isInterrupted()) {
//do stuff
}
}
public void shutdown() {
if (myThread != null) {
myThread.interrupt();
//do other shutdown stuff
}
}
}
public class MyClass {
public static void main(String[] args) {
Runnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable, "myRunnableThread");
t.start();
//do stuff
myRunnable.shutdown();
//do stuff
}
}
My question is, are there possible side effects or unknowns that holding a reference to your own thread, and providing limited access to that thread through public methods (as above) could cause? This is assuming that no-one ever calls the run() method directly, that it is always started from a new thread.
And I'm aware that I could use a volatile or atomic Boolean in the run() and shutdown() methods for communicating intent to shutdown, I'm more interested in learning than a solution. But solutions are still welcome!
For me your first approach is much better as less error prone and more "standard". But actually what you try to implement already exists (which proves that it makes sense and that it is not a bad practice but it is not easy to make it properly), it is called FutureTask, instead of shutdown you have cancel(boolean mayInterruptIfRunning) with true as value of mayInterruptIfRunning if you want to interrupt the thread running the task, I quote the javadoc:
Attempts to cancel execution of this task. This attempt will fail if
the task has already completed, has already been cancelled, or could
not be cancelled for some other reason. If successful, and this task
has not started when cancel is called, this task should never run. If
the task has already started, then the mayInterruptIfRunning
parameter determines whether the thread executing this task should be
interrupted in an attempt to stop the task.
For example:
// Task that will only sleep for 1 sec and print a message on interrupted
FutureTask<Void> myRunnable = new FutureTask<>(
new Callable<Void>() {
#Override
public Void call() throws Exception {
try {
System.out.println("Sleep");
Thread.sleep(1_000L);
} catch (InterruptedException e) {
System.out.println("Interrupted !!!");
throw e;
}
return null;
}
}
);
new Thread(myRunnable, "myRunnableThread").start();
// Wait long enough to make sure that myRunnableThread is sleeping
Thread.sleep(500L);
// Cancel the task and interrupt myRunnableThread
myRunnable.cancel(true);
Output:
Sleep
Interrupted !!!
It already has a reference:
Thread.currentThread()
From the javadoc:
Returns a reference to the currently executing thread object.
I have a thread in Java that makes a web call and stores the information retrieved, but it only retrieves information for that particular instant. I'd like to run this thread every second for a certain period of time to get a better view of the data. How can I do this? I've looked at ScheduledExecutorService, and from what I can tell if the thread is still running when it's time to set up the next run, it waits until the first thread is complete, which isn't what I'm looking for.
You can do this by a double schedule. Use scheduleWithFixedDelay() to set off a job every second. This job starts the method which you really want to run. Here is some code based on Oracle's ScheduledExecutorService API.
The Thread.sleep() is there to simulate a long-running task.
class Beeper {
public static void main(String[] args) {
(new Beeper()).beep();
}
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public void beep() {
final Runnable beeper = new Runnable() {
public void run() {
System.out.println("beep");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
final Runnable beeper2 = new Runnable() {
public void run() {
(new Thread(beeper)).start();
}
};
final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper2, 1, 1, SECONDS);
}
}
What you need is the scheduleAtFixedRate method: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html#scheduleAtFixedRate(java.lang.Runnable,%20long,%20long,%20java.util.concurrent.TimeUnit)
When the scheduler waits until the first thread is complete, it's because you're using scheduleWithFixedDelay.
However, if you absolutely want the threads run concurrently, you should try this:
pool.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
pool.submit(myJob);
}
}, 1, 1, TimeUnit.SECONDS);
I advise to always use a pool.
What about this?
public static void main (String [] args) throws InterruptedException{
ExecutorService executorService =
Executors.newFixedThreadPool(10);
while (true){
executorService.submit(new Runnable() {
#Override
public void run() {
// do your work here..
System.out.println("Executed!");
}});
Thread.sleep(1000);
}
}
This question already has answers here:
How to properly stop the Thread in Java?
(9 answers)
Closed 9 years ago.
I am having a problem trying to stop a thread instantly after a certain amount of time has elapsed, because thread.stop and similar others have been depreciated.
The thread that I am trying to stop uses my mouse and I need to stop it so that I can use my mouse in other ways.
What I was thinking is the code below, which was just to make another thread to watch how long the main thread has been running and if it is alive, stop it, but I can't accomplish this.
public void threadRun(int a) {
Thread mainThread = new Thread(new Runnable() {
#Override
public void run() {
// does things with mouse which may need to be ended while they
// are in action
}
});
Thread watchThread = new Thread(new Runnable() {
#Override
public void run() {
if (timeFromMark(mark) > a) {
if (mainThread.isAlive()) {
// How can I stop the mainThread?
}
}
}
});
}
You need to define a class for your second thread that extends runnable and pass the first thread as an argument.
Then you can stop the first thread.
But instead of doing this manually, have a look at the Java ThreadPoolExecuter and its awaitTermination(long timeout, TimeUnit unit) method. (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html )
Will save a lot of work.
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable r = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println("doing stuff");
Thread.sleep(10000);
System.out.println("finished");
} catch (InterruptedException e) {
System.out.println("Interrupted before finished!");
}
}
};
executor.execute(r);
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.SECONDS);
executor.shutdownNow();
} catch (InterruptedException e) {
//
}
System.out.println("Thread worker forced down. Continue with Application...");
Produces:
doing stuff
Interrupted before finished!
Thread worker forced down. Continue with Application...
Last two messages are nearly equal in terms of time and may change positions (its two different threads, continuing)
Java has deprecated methods for explicitly killing another thread (like Thread.stop / Thread.destroy). The right way is to make sure the operations on the other thread can handle being told to stop (for example, they expect an InterruptedException, which means you can call Thread.interrupt() in order to stop it).
Taken from How do I kill a thread from another thread in Java?
Killing/stopping threads is a bad idea. That's why they deprecated those methods. It's better to ask the thread to stop. E.g., something like the example below. (But note: if "do_something()" takes a long time, then you might want to use an interrupt to abort whatever it is.)
import java.util.concurrent.atomic.AtomicBoolean;
public class Stoppable {
private AtomicBoolean timeToDie = new AtomicBoolean(false);
private Thread thread;
public void start() {
if (thread != null) {
throw new IllegalStateException("already running");
}
thread = new Thread(new Runnable() {
public void run() {
while (!timeToDie.get()) {
// do_something();
}
}
});
thread.start();
}
public void stop() throws InterruptedException {
timeToDie.set(true);
thread.join();
thread = null;
}
}
I want to know the best way how to notify another thread. For example, I have a background thread:
public void StartBackgroundThread(){
new Thread(new Runnable() {
#Override
public void run() {
//Do something big...
//THEN HOW TO NOTIFY MAIN THREAD?
}
}).start();
}
When it finished it has to notify main thread? If somebody knows the best way how to do this I'll appreciate it!
The typical answer is a BlockingQueue. Both BackgroundThread (often called the Producer) and MainThread (often called the Consumer) share a single instance of the queue (perhaps they get it when they are instantiated). BackgroundThread calls queue.put(message) each time it has a new message and MainThread calls 'queue.take()which will block until there's a message to receive. You can get fancy with timeouts and peeking but typically people want aBlockingQueueinstance such asArrayBlockingQueue`.
Purely based on your question you could do this:
public class test
{
Object syncObj = new Object();
public static void main(String args[])
{
new test();
}
public test()
{
startBackgroundThread();
System.out.println("Main thread waiting...");
try
{
synchronized(syncObj)
{
syncObj.wait();
}
}
catch(InterruptedException ie) { }
System.out.println("Main thread exiting...");
}
public void startBackgroundThread()
{
(new Thread(new Runnable()
{
#Override
public void run()
{
//Do something big...
System.out.println("Background Thread doing something big...");
//THEN HOW TO NOTIFY MAIN THREAD?
synchronized(syncObj)
{
System.out.println("Background Thread notifing...");
syncObj.notify();
}
System.out.println("Background Thread exiting...");
}
})).start();
}
}
and see this output
PS C:\Users\java> javac test.java
PS C:\Users\java> java test
Main thread waiting...
Background Thread doing something big...
Background Thread notifing...
Background Thread exiting...
Main thread exiting...
Just call notify()
public void run() {
try {
while ( true ) {
putMessage();
sleep( 1000 );
}
}
catch( InterruptedException e ) { }
}
private synchronized void putMessage() throws InterruptedException {
while ( messages.size() == MAXQUEUE )
wait();
messages.addElement( new java.util.Date().toString() );
notify();
}
You can't "notify the main thread".
The best approach is to use an ExecutorService, like this for example:
import java.util.concurrent.*;
// in main thread
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<?> future = executorService.submit(new Runnable() {
#Override
public void run() {
//Do something big...
}
});
future.get(); // blocks until the Runnable finishes
The classes are written specially to deal with asynchronous operations, and all the code in there is already written for you and bullet-proof.
Edit
If you don't want to block the main thread while waiting, wait within another thread:
final Future<?> future = executorService.submit(new Runnable() {
#Override
public void run() {
//Do something big...
}
});
new Thread(new Runnable() {
#Override
public void run() {
future.get(); // blocks until the other Runnable finishes
// Do something after the other runnable completes
}
}).start();
One thread notifying another thread is not a good way to do it. Its better to have 1 master thread that gives the slave thread work. The slave thread is always running and waits until it receives work. I recommend that you draw two columns and determine exactly where each thread needs to wait.
public void run()
{
//Do something big...
synchronized(this)
{
done = true;
}
}
Java includes libraries that make this really easy see ExecutorService and the following post
Producer/Consumer threads using a Queue
I need to run some code after a period of time without blocking the current method.
I tried the following 2 approaches:
public static void main(final String[] args) {
System.out.println("Start");
Timer t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
System.out.println("done");
this.cancel();
}
}, 4000L);
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.schedule(new Runnable() {
public void run() {
System.out.println("done");
}
}, 2, TimeUnit.SECONDS);
executor.shutdown();
System.out.println("Stop");
}
The problem is that the first does block the app and the second does not allow main to exit until it finishes;
How to run the code after some time and exit the current method right after scheduling it ?
You could create a own thread and set it as Daemon:
final Thread myThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(20000);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("20 seconds over");
}
});
myThread.setDaemon(true);
myThread.start();
An alternative is to create the Executor with a ThreadFactory, in which you set the created Thread as Daemon. You have to use these function:
Excecutors.newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
If you want the job you create to outlive the java process that created it, then you will have to launch another process. Commons exec can help with that, since launching a process from java is not as simple as it may first appear.
If you set the thread as daemon then your process exits, then the daemon thread will also be killed - its address space is gone.
Use a ScheduledExecutor
Use a scheduled executor:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
It has a schedule method, a schedule at fixed rate method and a schedule with fixed delay method.