I'm a newbie in Java and I haven't work with threads in past. Now I have a really tricky issue for my level of knowledge.
I have developed two functionalities the "Send mail" and the "Check mail". Each user register his preferences and the system creates two catalogues with many instructions for periodic work like
A) send message every 1500 msec
B) send message every 1800 msec
C) send message every 3000 msec
And
A) check message every 2000 msec
B) check message every 6000 msec
C) check message every 8000 msec
I tried many ways with threads but I fail to do it work.
My question is which is the best way to synchronize them? Below is code from my last effort using threads.
public class MailCreatorThread extends Thread {
#Override
public void run() {
CreateMail(_date); //creates a mail with _date as subject
}
}
public class GPSThread extends Thread {
#Override
public void run() {
// TODO Auto-generated method stub
while (!_isTimeToStop) {
try {
while (_servicesToUpdate.size() == 0) {
Thread.sleep(500);
}
_currentService = (MyService) _servicesToUpdate.get(0)
.clone();
_servicesToUpdate.remove(0);
MailCreatorThread mailCreatorThread = new MailCreatorThread();
mailCreatorThread.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class CheckServicesThread extends Thread {
#Override
public void run() {
// TODO Auto-generated method stub
while (!_isTimeToStop) {
try {
Thread.sleep(1000);
for (int j = 0; j < _servicesList.length; j++) {
MyService currentService = ((MyService) _servicesList[j]);
if (myService.getTimeToNextUpdate() - 1000 <= 0) {
_servicesToUpdate
.add((MyService) currentService
.clone());
currentService
.setTimeToNextUpdate(currentService
.getUpdatePeriod());
} else {
currentService
.setTimeToNextUpdate(currentService
.getTimeToNextUpdate() - 1000);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
stopSelf();
}
}
You can use a ScheduledExecutorService to run thos periodic tasks. The syntax is fairly straightforward:
Runnable check = new Runnable() {
public void run() {
checkMessage();
}
}
Runnable send = new Runnable() {
public void run() {
sendMessage();
}
}
//since what you are doing is mostly I/O you probably want to have
//more than one thread available so that if one operation blocks,
//the other ones can be launched in parallel
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
scheduler.scheduleAtFixedRate(check, 0, 1500, MILLISECONDS);
scheduler.scheduleAtFixedRate(send, 0, 6000, MILLISECONDS);
Note: Timer mentioned in Ozzy's answer should not be used any more as it has been improved in Java 1.5 by ScheduledThreadPoolExecutor, as explained in Timer's javadoc :
Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for the Timer/TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn't require subclassing TimerTask (just implement Runnable). Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer.
In java you have built-in Timer and TimerTask classes to help you repeat a task in a separate thread.
This will create a Timer which will create its own background Thread:
Timer t = new Timer();
You can then schedule as many tasks as you want to that timer, they will share the timer's own thread.
This is how you can schedule a single task on the timer thread, after a delay of 2000ms = 2s:
t.schedule(new TimerTask() {
#Override
public void run() {
//task to perform
}
}, 2000);
This is how you can schedule a repeated task on the timer thread, after a delay of 1s, and repeat the task at 1.5s intervals:
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//task to perform every 1.5 seconds
}
}, 1000, 1500);
Now you have a choice to schedule both tasks (checkMail, sendMail) to the same Timer (same thread) or give them each their own Timer (separate threads).
For more info, refer to the java docs (http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html)
Hope this helps.
Related
I want to run a task at every particular interval of time regardless of completion of previous thread. And I've used ScheduledExecutorService with the schedule time at every one second. But the problem is, in my Runnable, If I make thread to sleep for 5 seconds, My ScheduledExecuterService also getting executed in every 5 seconds while it supposed to run each thread at 1 second.
It seems like it ScheduledExecuterService is waiting for previous thread to completion. But I want, The task to be triggered at every 1 second no matter what if job inside the task waits for longer time.
Here's is my code.
public class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And here's my ScheduledExecutorService Code.
public class JavaScheduledExecutorServiceExample {
public static void main(String[] args) {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(5);
execService.scheduleAtFixedRate(new MyTask(), 0, 1000, TimeUnit.MILLISECONDS);
}
}
Correct me If I'm doing something wrong. And If I'm wrong, is there any alternative to achieve the same? Providing Any best practices could be more helpful :)
"If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute." The behavior you are seeing is consistent with the javadocs
I believe this will perform the way you specified:
public class JavaScheduledExecutorServiceExample {
private static ScheduledExecutorService execService = null;
private static int timesAsleep = 0;
public static class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
// schedule again
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
try {
int i = timesAsleep;
timesAsleep++;
System.out.println("asleep " + i + "----------------------");
Thread.sleep(5000);
System.out.println("awoke " + i + "----------------------");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
execService = Executors.newScheduledThreadPool(5);
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
}
}
Notice the use schedule() instead of scheduleAtFixedRate() on the ScheduledExecutorService instance. It also schedules the next task as soon as it starts the new task.
I am planning on implementing a timer service for my java application.
The core structure is like so.
In the Base class, I call scheduleATassk() to start the first task with delay set. When the delay is up, it will call onTimeUp() to notify me that we can calculate the next alarm duration. So in onTimeUp(), if the conditions are met, i will call scheduleATassk() with the new duration and the cycles repeats.
My question is:
The very first task will be scheduled by the main thread (notice in the Base class's constructor (the main thread), it calls scheduleATassk() to get the alarm running). However, any subsequent scheduleATassk() will be call by the child thread. Are there any effect? Is it safe? Can I improve on the design?
public class Base {
private ScheduledExecutorService service = null;
public Base() {
service = Executors.newSingleThreadScheduledExecutor();
scheduleATassk(10);
}
public void onTimeUp() throws Exception {
if (hasMoreTime) {
scheduleATassk(newCalculatedDuration);
} else {
System.out.println("TIMER IS UP");
}
}
protected void scheduleATassk(long duration) {
service.schedule(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
onTimeUp();
}
}, duration, TimeUnit.MILLISECONDS);}
}
}
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 am trying to make an ExecutorService implementation that can be provided with a timeout or interrupt for each thread.
In my below example, suppose I am spawning 2 threads (in actual scenario, this number will be high), then I need to make sure each thread should be running for 10 minutes.
That means, Thread1 will run for 10 minutes and Thread2 will run for 10 minutes as well. If 10 minutes is over then I need to interrup the thread or timeout.
Below is the code I have so far and I am not able to understand how should I add this interrupt or timeout functionality here in such a clean way so that if I am making this no of threads parameter configurable in my code then it should work properly there as well.
public static void main(String[] args) {
final int noOfThreads = 2;
final long exp_time_millis = 600000; //10 minutes
//create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(noOfThreads);
for (int i = 0, i< noOfThreads; i++) {
service.submit(new ThreadTask());
}
}
class ThreadTask implements Runnable {
#Override
public void run() {
while(true) {
System.out.println("Thread running...");
try {
/* make a select sql to the database
* and measure how much time it is taking in
* returning the response
*/
} catch (InterruptedException e) {
}
}
}
}
Any suggestions will be of great help.
I have already seen few articles on the SO but I was not able to find anything which matches my scenario and I can implement that easily.
Updated Code:-
I am trying the below code but it gives me error on the catch block in the run method. Not sure if I am doing anything wrong. Can anyone help me?
public class ThreadTimeout {
public static void main(String[] args) {
final int noOfThreads = 2;
//create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(noOfThreads);
ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(noOfThreads);
for (int i = 0; i< noOfThreads; i++) {
final Future future = service.submit(new ThreadTask());
scheduleService.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, 10, TimeUnit.MINUTES);
}
}
}
class ThreadTask implements Runnable {
#Override
public void run() {
//make a database connection
while (true) {
System.out.println("Thread running...");
try {
/*
* make a select sql to the database and measure
* how much time it is taking in returning the
* response
*/
} catch (InterruptedException e) {
}
}
}
}
I would recommend using a second ScheduledExecutorService. You can submit the Future returned from your original submissions to the ScheduledExecutorService to cancel.
ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(n);
for (int i = 0, i< noOfThreads; i++) {
final Future future = service.submit(new ThreadTask());
scheduleService.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, 10, TimeUnits.MINUTES);
}
Now the ThreadTask needs to respond to interruption or else this will not help.
What I would recommend is to use the ExecutorService.awaitTermination(...); method and then the ExecutorService.shutdownNow() method.
For example:
for (int i = 0; i < noOfThreads; i++) {
service.submit(new ThreadTask());
}
// we always need to shutdown the service _after_ we've submitted all jobs
service.shutdown();
// now we wait for those tasks to finish for 10 minutes
if (!service.awaitTermination(10, TimeUnit.MINUTES)) {
// if we timed out waiting for the tasks to finish, forcefully interrupt them
service.shutdownNow();
}
Note that this will interrupt the threads but that will only cause certain methods such as Thread.sleep(), Object.wait(), and some others to throw InterruptedException. It also sets the interrupt bit on the thread which can be tested with Thread.currentThread().isInterrupted(). It will not "kill" the thread like you would a unix process.
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.