I need to make a Thread which starts it's work at the time the program runs and dies when the program is closed. this Thread is going to check something every 1 minute ones.
what is the best way for this scheduling, using Thread.sleep() or using a Timer or what?
You've not provided any code, but there's loads of examples about for this sort of thing, here's one:
import static java.util.concurrent.TimeUnit.*;
class BeeperControl {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public void beepForAnHour() {
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
final ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
scheduler.schedule(new Runnable() {
public void run() { beeperHandle.cancel(true); }
}, 60 * 60, SECONDS);
}
}
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledExecutorService.html#scheduleAtFixedRate(java.lang.Runnable
Create a ScheduledExecutorService throught Executors#newSingleThreadScheduledExecutor()
Schedule your thread with ScheduleExecutorService#scheduleAtFixedRate
At the end of your application, call ScheduledExecutorService#shutdownNow()
So you will have something like
public class Application {
private final ScheduledExecutorService executor;
private final Runnable task;
public Application(ScheduledExecutorService executor, Runnable task) {
this.executor = executor;
this.task = task;
}
public void init() {
executor.scheduleAtFixedRate(task, 0, 60, TimeUnit.SECONDS);
}
public void shutdown() {
executor.shutdownNow();
}
}
and you will create your application with something like
// ....
Application app = new Application(Executors.newSingleThreadScheduledExecutor(), task);
app.init();
// ....
// at end
app.shutdown();
To make a Thread which starts it's work at the time the program runs and dies when the program is closed, mark this thread as a daemon thread:
Thread myThread=new Thread();
myThread.setDaemon(true);
myThread.start(); // forget about it, no need to explicitly kill it
Related
I have a simple java program I use to generate elements and insert them in DB every X seconds during a specific time.
The generation is done with a scheduleAtFixedRate. there is only one of these.
I want my program to quit completely when the scheduled task is over. To do so, I use System.exit() when the task is canceled, but is it the correct way to do this ?
Here is my current code:
public static void main(String[] args) throws InterruptedException {
c = generateDbConnection(url, user, password);
if (c != null) {
s = generateDbStatement(c);
} else {
System.out.println("ERROR");
return;
}
initialTimestamp = new Date();
TimeUnit.SECONDS.sleep(1);
generateForAnHour();
}
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
/**
* Generator thread handler Uses Statement from main function
*/
public static void generateForAnHour() {
final Runnable runner = new Runnable() {
public void run() {
String[][] data = new String[numberOfIds][2];
for (int i = 0; i < numberOfIds; i++) {
data[i] = generateDevice();
insertDevice(s, data[i][0], data[i][1]);
}
quantityOfIds += numberOfIds;
}
};
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 5, TimeUnit.SECONDS);
scheduler.schedule(new Runnable() {
public void run() {
generatorHandle.cancel(true);
System.out.println("Scheduled ID generator terminated.");
System.exit(0); //TODO Is it really correct way to do it
}
}, timeToRun, TimeUnit.SECONDS);
}
I am not sure if this is the correct way to stop the execution of your program if it has some more functions, but I, personally, find it an OK way. :D
So, as it turned out, ScheduledExecutorService seemingly creates non-daemon threads with its default ThreadFactory, perhaps we need to supply a daemonic one to it.
However, if we are to call ExecutorService#shutdown or the forceful ExecutorService#shutdownNow, it will stop both tasks from executing, thus removing the thread(s) that prevent the application from ending its job:
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public static void main(String[] args) {
// Some service code here
generateForAnHour();
}
public static void generateForAnHour() {
// Some code that does work
final Runnable runner = () -> System.out.println("Running...");
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 1, TimeUnit.SECONDS);
// Code that interrupts the worker after a specified time
scheduler.schedule(scheduler::shutdown, 5, TimeUnit.SECONDS);
}
Output:
Running...
Running...
Running...
Running...
Running...
Running...
Process finished with exit code 0
I hope this will help. :D
This answer is secondary to this one, but it has a different way to solve the problem, so I thought it is appropriate enough to create a separate answer.
If you want to have some more tasks in the future, I believe this solution is more scalable and is more "correct thing".
It creates daemon threads for both runner and interrupter. I think it would be better to create a normal thread factory for the interrupter, but I failed to make it working, so it's better to stick to my first answer...
Here generateForAnHour returns a Future that is used to wait for the time needed.
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1 , new ThreadFactory() {
#Override
public Thread newThread(final Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});
public static void main(String[] args) throws InterruptedException, ExecutionException {
// Some service code here
generateForAnHour().get();
}
public static ScheduledFuture<Boolean> generateForAnHour() {
// Some code that does work
final Runnable runner = () -> System.out.println("Running...");
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 1, TimeUnit.SECONDS);
// Code that interrupts the worker after a specified time
return scheduler.schedule(() -> generatorHandle.cancel(false), 5, TimeUnit.SECONDS);
}
If you won't call Future#get, you'll receive only one Running... in best case or none at all.
If you decide to return the runner future, you'll probably get nasty CancellationException in the get() call:
Exception in thread "main" java.util.concurrent.CancellationException
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:121)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at com.xobotun.Test.main(Test.java:30)
I'd use the ExecutorService::shutdown approach as the stabler and more understandable one. :D
How would I create a thread that will execute after a delay of s seconds?
I would like other processes to run while the thread is waiting.
For example, I would like to create the thread, then print out several other strings, then after s seconds, the thread will run.
What I don't need is the whole program to wait for s seconds, then everything happens. I need processes to run while the delay is ticking.
Thanks!
~Java preferred
Use a ScheduledExecutorService. See the example below.
System.out.println("some stuff");
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable task = new Runnable() {
#Override
public void run() {
System.out.println("do something");
}
};
Future<?> futureHandle = scheduler.scheduleWithFixedDelay(task, 10, 10, TimeUnit.SECONDS);
System.out.println("some other stuff");
The task is scheduled with a fixed delay of 10 seconds, so you'll get output for the print statements not in the Runnable followed by the one in the Runnable every 10 seconds.
The output in this example is
some stuff
some other stuff
do something
do something
...
with the "do something" lines occurring at 10 sec. intervals after an initial 10 sec. delay.
To stop it, you can create a "stop" task to put some kind of logic in, and register that.
final Runnable stopTask = new Runnable() {
#Override
public void run() {
futureHandle.cancel(true); // true: interrupt if necessary
}
};
long delay = // some number, how long to wait before invoking the stop task
scheduler.schedule(stopTask, delay, TimeUnit.SECONDS).get(); // wait if necessary and get the future result
scheduler.shutdown(); // shutdown on completion
EDIT
If you just need the task to run once, as pointed out in the comments, consider a TimerTask:
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("timer task");
timer.cancel(); // stop timer after execution
}
};
timer.schedule(task, 1000); // schedule task with delay of 1000ms
I would suggest you to take look into quartz scheduler. This is very powerful and does almost similar tasks like unix cron in java environment.
There are bunch of tutorials online for quartz that you can always look into.
Here is one working example with Thread.sleep():
public class DelayThread implements Runnable {
private final int DELAY;
public DelayThread(int delay) {
this.DELAY = delay;
}
#Override
public void run() {
try {
Thread.sleep(DELAY);
System.out.println("task executed");
} catch (InterruptedException ex) {
System.out.println("interrupted");
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new DelayThread(2000));
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread(new DelayThread(2000));
thread2.start();
System.out.println("All threads are started");
}
}
I have a scheduled task in my program that closes a frame after a given period of time. However, after the task has been executed, the program keeps running as if the ScheduledExecutorService was still running on a different thread.
This is the relevant part of my code:
int delay = 1000;
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(() -> {
System.out.println("executed");
getWindow().closeWindow();
// ex.shutdown();
}, delay, TimeUnit.MILLISECONDS);
Here the task is executed after a 1 second delay, "executed" is printed once, the frame closes, and the program keeps running even after this code. If I uncomment the ex.shutdownNow();, the program successfully ends as intended. However, I cannot figure out why this is happening. I also failed to find anything from the rest of the Internet.
MCVE:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
int delay = 1000;
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(() -> {
System.out.println("executed");
// ex.shutdown();
}, delay, TimeUnit.MILLISECONDS);
}
}
The lambdas might've given it away, but this is indeed Java 8.
Why is the program not stopping after the task has been executed?
The ScheduledExecutorService thread pool returned by Executors#newSingleThreadScheduledExecutor() uses non daemon threads. Until you shut down the thread pool, these are still alive awaiting tasks. A JVM does not end while non-daemon threads are alive.
You can use the overloaded Executors#newSingleThreadScheduledExecutor(ThreadFactory) and provide your own ThreadFactory implementation which creates daemon threads. Note that this risks the case where your task may not even run because the JVM would exit before the task's scheduled time.
Do as you've discovered and shut it down. Note that you should shut always it down somewhere safe, where the operation can't fail.
The Java Virtual Machine runs until all threads that are not daemon threads have died. And Executors.defaultThreadFactory() creates each new thread as a non-daemon thread. However, there is an overload of Executors.newSingleThreadScheduledExecutor(); which takes a ThreadFactory as a parameter, if you care to venture in that direction.
public static void main(String[] args) {
int delay = 1000;
class DaemonFactory implements ThreadFactory
{
#Override
public Thread newThread(Runnable r)
{
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
ThreadFactory tf = new DaemonFactory();
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(tf);
ex.schedule(() -> {
System.out.println("executed");
}, delay, TimeUnit.MILLISECONDS);
}
I would approach this entirely differently. You state:
I have a scheduled task in my program that closes a frame after a given period of time.
Why not instead use a Swing Timer for this as this was built to work well with the Swing event thread?
new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
((Timer) e.getSource()).stop();
someWindow.dispose();
}
}).start();
You can call shutdown from ScheduledExecutorService as it will wait for thread execution and then finalize thread pool. As you can see in Javadoc: "Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will
be accepted. Invocation has no additional effect if already shut down."
Example:
...
scheduledExecutorService.schedule(runnable, delay, TimeUnit.MILLISECONDS);
scheduledExecutorService.shutdown();
...
I am starting scheduler from onCreate() and stopping it in onDestroy() approach to stop the scheduler service.
public MyActivity extends Activity
{
ScheduledExecutorService scheduledExecutorService;
ScheduledFuture<?> scheduledFuture;
private int apiThreshold = 10;//seconds
onCreate()
{
startScheduler();
}
onDestroy()
{
if (scheduledFuture != null)
{
stopScheduler();
}
shutDownService();
super.onDestroy();
}
public void startScheduler() {
Debug.e(TAG, "inside start scheduler");
scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// call method to do your task/perform your repeated task
}
}, 4, apiThreshold, TimeUnit.SECONDS);
}
public void shutDownService()
{
if (scheduledExecutorService != null) {
Log.e(“test,"in shutDown service close if not null");
scheduledExecutorService.shutdownNow(); // shutdown will allow the final iteration to finish
// executing where shutdownNow() will kill it immediately
Log.e(“test,"is service shutdown(true/false)=="+scheduledExecutorService.isShutdown());
}
}
}
Just as mentioned, can we make one thread as daemon thread, and execute some detection codes on detecting other threads status? i hope the daemon thread will be executed every 5 mins(more or less, inaccuracy can't be huge, several seconds delay are acceptable)
Have a look at this:
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor svc = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t1 = new Thread(r);
t1.setDaemon(true);
return t1;
}
});
svc.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
System.out.println("Himanshu "+Thread.currentThread().getName());
}
}, 5, 5, TimeUnit.SECONDS);
svc.awaitTermination(10000, TimeUnit.SECONDS);
}
Look here first, like #Azodious said. The job you want to schedule is using ThreadMXBeans. See sample core here.
class BeeperControl {
private final static ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public static void main(String[] args){
beepForAnHour();
}
public static void beepForAnHour() {
final Runnable beeper = new Runnable() {
public void run() {
System.out.println(“beep”);
}
};
final ScheduledFuture beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
scheduler.schedule(new Runnable() {
public void run() {
beeperHandle.cancel(true);
}
}, 60 * 60, SECONDS);
}
}
This code beeps every 10 seconds for an hour. How do i make it beep for every 10minutes forever. as in it should keep beeping every 10mins forever(not just for an hour)
You explicitly schedule a cancel task. If you don't want to cancel, then don't schedule the cancelling task.
Just remove the 2nd schedule that does the cancel.
I propose:
public void run() {
while(true) {
System.out.println(“beep”);
Thread.sleep(10000);
}
}
+'s;
Simpler
You can track if you're being Interrupted
-'s:
- You have to catch the InterruptedException
If you want to stop:
Put code to stop/pause in the catch statement and say myThread.interrupt(); to stop, starting it again is a bit harder, your best option is to create a new Thread (that does exactly the same). Info here: How to start/stop/restart a thread in Java?
Put an if-statement in the while-loop, checking a public boolean isRunning, if it's false, say continue; an recheck again and again until it is true again, put your beeping code in the 'true-block'.