Is there a way to completely stop a task in java? - java

I want a task to run at scheduled interval and timeout if it does not complete in required time and continue further iteration.
I have gone through the following answers, but it doesn't address my problem..
How do you kill a Thread in Java?
ExecutorService that interrupts tasks after a timeout
Consider the following case
BasicThreadFactory collectionFactory = new BasicThreadFactory.Builder()
.namingPattern("CollectionExecutor-%d")
.build();
// thread pool size is set 2
// 1-for scheduler thread which runs task and tracks timeout
// 2-for task itself
ScheduledExecutorService collectionExecuter =
Executors.newScheduledThreadPool(2, collectionFactory);
// fires collection every minute and if it is in between execution during
// scheduled time then waits for completion and executes immediately
// after it
//my task:
Runnable runnable= new Runnable() {
#Override
public void run() {
try {
System.out.println("Executed started");
Thread.sleep(2000);
System.out.println("Executed after .get method call.");
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(20000);
System.out.println("Executed even after .cancel method " +
"call (I want this to avoid this.)");
} catch (Exception e) {
e.printStackTrace();
}
}
};
Above task should run with an interval of 3 sec and stop if it takes more than 1 sec...Consider It is not possible to have complete task in single try catch block, now how could I stop the task to wait further in next sleep(20000) and continue with next iteration.
collectionExecuter.scheduleAtFixedRate(new Runnable() {//scheduler thread
#Override
public void run() {
try {
Future<?> future = collectionExecuter.submit(runnable);
try {
future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
future.cancel(true);
System.out.println("Collection thread did not " +
"completed in 1 Sec.Thread Interrupted");
}
} catch (Exception e) {
System.out.println("Unable to start Collection Thread");
}
}
}, 0, 3, TimeUnit.SECONDS);
}

Related

Java thread hangs after CompletionService.take()

I've got simple test code:
public static void main(String[] args) {
CompletionService<Integer> cs = new ExecutorCompletionService<>(Executors.newCachedThreadPool());
cs.submit(new Callable<Integer>() {
public Integer call(){
try{
Thread.sleep(3000); // Just sleep and print
System.out.println("Sleeping thread: " + Thread.currentThread().getId());
}catch(InterruptedException e){
e.printStackTrace();
}
return 10;
}
});
try{
Future<Integer> fi = cs.take();
System.out.println(fi.get());
}catch(Exception e){
e.printStackTrace();
}
}
I run it, sleep 3 seconds, and prints
Sleeping thread: 14
10
But then it hangs there, the program doesn't end.
What's happening, how to make it finish?
As mentioned in the comments by tgdavies, your program will exit after +/- 60 seconds, because that is the default timeout for a thread without tasks in an ExecutorService created by Executors.newCachedThreadPool().
If you don't want to wait for 60 seconds, you should shutdown the executor service after you're done submitting tasks.
For example:
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
try {
CompletionService<Integer> cs = new ExecutorCompletionService<>(executorService);
cs.submit(new Callable<Integer>() {
public Integer call() {
try {
Thread.sleep(3000); // Just sleep and print
System.out.println("Sleeping thread: " + Thread.currentThread().getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}
});
try {
Future<Integer> fi = cs.take();
System.out.println(fi.get());
} catch (Exception e) {
e.printStackTrace();
}
} finally {
executorService.shutdown();
}
}
Alternatively, configure the executor service to create daemon threads using a custom ThreadFactory. Only do this if it is not a problem that an executor service that is doing actual work gets "killed" when there are no more normal (non-daemon) threads.

Non interrupted code running via Executor Service

Im familiar with the fact that we as developers need to add a check for interrupts in our code when we write something that might run async via threads.
The following example shows the wrong case, when there is no check for interrupt in the runnable and therefore even if I got timeout exception on the main thread, the child thread keep running the task :
public void myTest() throws InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Void> future = executorService.submit(() -> {
while (true) {
log.info("test");
Thread.sleep(40);
}
});
try {
future.get(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
Thread.sleep(500);
log.info("done");
output :
test
test
test
java.util.concurrent.TimeoutException
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)
at myFile.myTest(MyFile.java:102)
test
test
test
test
done
By adding future.cancel(true) I got an unexpected behavior. According to what I understood, the cancel(boolean) method wont stop the task, if the task is already running, it might only interrupt it and thats all.
The code :
public void myTest() throws InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Void> future = executorService.submit(() -> {
while (true) {
log.info("test");
Thread.sleep(40);
}
});
try {
future.get(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} finally {
boolean value = future.cancel(true);
log.info(""+value);
}
Thread.sleep(500);
log.info("done");
The output :
test
test
test
java.util.concurrent.TimeoutException
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)
at myFile.myTest(MyFile.java:102)
true
done
So why by adding the future.cancel(true) the runnable stopped running ? I expected that during the 500 mili seconds that the main thread sleeps, I will see more test prints like I saw in the previous example.
When you call future.cancel(true), it will try to interrupt your executor thread. Executor thread will receive InterruptedException and die. That's where your FutureTask stops executing.

ScheduledExecutorService waits for task to complete, does pending tasks pile up to ultimately interrupting main thred?

I was curious for my new implementation using ScheduledExecutorService in which the task is expected to finish within 100ms period and 0ms delay. But in case if there is system load and its taking say 550 ms, would there be a queue maintained by ScheduledExecutorService for those pending 4 tasks? And then run as soon as (0ms delay) first one is finished. And what if second execution takes 560 ms , would that add another 4 threads to its queue?
There is not documentation around that, or I might be overlooking it. But I want to make sure that the pile up of such executions would trigger to leak or overflow.
For example: below code, could main thread ever fail?
private static ScheduledExecutorService consumerThreadPool = Executors.newSingleThreadScheduledExecutor();
public static void main(String[] args) throws Exception {
consumerThreadPool.scheduleAtFixedRate(() -> performTask(), 0, 1, TimeUnit.MILLISECONDS);
}
private static void performTask () {
try {
Thread.sleep(550);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Your tasks will be skipped if they overrun the next scheduled time, you can verify easily with System.out.println and alter the sleep under 500ms to 5000ms:
public static void main(final String[] args) throws InterruptedException, ExecutionException
{
var executor = Executors.newScheduledThreadPool(1);
var count = new AtomicInteger();
Runnable task = () -> {
String desc = "run("+((System.currentTimeMillis() / 1000) % 60)+") "+Thread.currentThread().getName()+" count "+count.incrementAndGet();
System.out.println(desc);
if(count.get() == 50)
throw new RuntimeException("I give up!");
try
{
Thread.sleep(2500);
}
catch (InterruptedException e)
{
System.out.println("Thread "+Thread.currentThread().getName()+" INTERRUPTED");
}
};
var future = executor.scheduleAtFixedRate(task, 5000, 1000, TimeUnit.MILLISECONDS);
System.out.println("Calling future.get() ...");
try {
var res = future.get();
System.out.println("future.get()="+res);
}
catch(Exception e)
{
System.err.println("There was an exception:" +e);
// Decide between "continue" or "throw e" here
// ...
}
executor.shutdownNow();
System.out.println("shutdown complete");
}

java simple thread, but it can't run

it's a simple java thread.
there are 2 threads, and it should be printed every 5 second.
there's no error.
but i just can't run.
please help me finding out what's wrong...
class MyThread extends Thread {
String message;
int delay;
public MyThread(String s, int d) {
message = s;
delay = d;
}
public void run() {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
System.out.println(message + "+" + delay );
}
}
}
public class applet {
public static void main(String[] args){
MyThread mt1, mt2;
mt1 = new MyThread("Hello", 5000);
mt2 = new MyThread("Bye ", 10000);
mt1.start();
mt2.start();
}
}
You are printing ONLY ONCE if an exception occurs...
Modify the run method to:
public void run() {
try {
Thread.sleep(delay);
System.out.println(message + "+" + delay );
} catch (InterruptedException e) {
System.err.println("error here" );
}
}
There are actually 2 mistakes in your program:
1. Print your message in the normal flow
So far you only print your message when you get an InterruptedException which is an exception that is thrown when your thread has been interrupted while sleeping. So instead of printing your message in the catch block, you are supposed to print it after the sleep as next:
try {
Thread.sleep(delay);
System.out.println(message + "+" + delay );
} catch (InterruptedException e) {
// Re-set the interrupted flag
Thread.currentThread().interrupt();
}
2. Add an infinite loop
As you wish to print your message every 5 seconds, you need to call sleep in an infinite loop otherwise your thread will print it only once and die, so the code should be at the end:
try {
while (true) {
Thread.sleep(delay);
System.out.printf("%s+%d%n", message, delay);
}
} catch (InterruptedException e) {
// Re-set the interrupted flag
Thread.currentThread().interrupt();
}
3. Bonus
Alternatively, you can use a ScheduledExecutorService to schedule your tasks with a fixed rate using the method scheduleAtFixedRate, your code would then be:
// Create a ScheduledExecutorService of 2 threads
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// Schedule my task every 5 seconds starting in 5 seconds
executor.scheduleAtFixedRate(new MyTask("Hello", 5000), 5L, 5L, TimeUnit.SECONDS);
// Schedule my task every 10 seconds starting in 10 seconds
executor.scheduleAtFixedRate(new MyTask("Bye ", 10000), 10L, 10L, TimeUnit.SECONDS);
The class MyTask would simply be:
class MyTask implements Runnable {
String message;
int delay;
public MyTask(String s, int d) {
message = s;
delay = d;
}
public void run() {
System.out.printf("%s+%d%n", message, delay);
}
}

In Java: how can I make thread watch over another thread?

Sorry if the question is quite simple. I am a beginner.
I have to create thread that calulates something, while the first thread works the other one have to measure if the first thread calculate the function in specified time. If not, it has to throw exception. Else it returns the answer.
I'd take the java.util.concurrent components - simple example
public void myMethod() {
// select some executor strategy
ExecutorService executor = Executors.newFixedThreadPool(1);
Future f = executor.submit(new Runnable() {
#Override
public void run() {
heresTheMethodToBeExecuted();
}
});
try {
f.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// do something clever
} catch (ExecutionException e) {
// do something clever
} catch (TimeoutException e) {
// do something clever
}
}
Have your thread notify a synchronization object when it is done and have your other thread wait x number of milliseconds for it to finish.
public class Main {
private static final Object mThreadLock = new Object();
static class DoTaskThread extends Thread {
public void run() {
try {
int wait = new Random().nextInt(10000);
System.out.println("Waiting " + wait + " ms");
Thread.sleep(wait);
} catch (InterruptedException ex) {
}
synchronized (mThreadLock) {
mThreadLock.notifyAll();
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
synchronized (mThreadLock) {
DoTaskThread thread = new DoTaskThread();
thread.start();
try {
// Only wait 2 seconds for the thread to finish
mThreadLock.wait(2000);
} catch (InterruptedException ex) {
}
if (thread.isAlive()) {
throw new RuntimeException("thread took too long");
} else {
System.out.println("Thread finished in time");
}
}
}
}
join is a lot simpler than using a lock.
join (millis)
Waits at most millis milliseconds
for this thread to die. A timeout of 0
means to wait forever.
Example code:
Thread calcThread = new Thread(new Runnable(){
#Override
public void run() {
//some calculation
}
});
calcThread.start();
//wait at most 2secs for the calcThread to finish.
calcThread.join(2000);
//throw an exception if the calcThread hasn't completed.
if(calcThread.isAlive()){
throw new SomeException("calcThread is still running!");
}
Have a look at http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long,%20java.util.concurrent.TimeUnit) which allows you to handle this without dealing with thread synchronization yourself.

Categories

Resources