Method optimization in java - java

I'm new to Java. I'm trying to optimize following method:
public void myLongRunningMethod()
{
LongRunningOperation1();
LongRunningOperation2();
LongRunningOperation3();
Log.Info("completion message goes here.")
}
LongRunningOperation1(),LongRunningOperation2() and LongRunningOperation3() are independant of each other and the order of their completion does not matter.
But the log statement should be printed only after successful completion of all these method calls.
If I take the following approach, since its using a new thread, I believe the order of completion of methods wont be guarenteed.
public String myMethod()
{
Thread thread1 = new Thread(() -> {
LongRunningOperation1();
}).start();
Thread thread2 = new Thread(() -> {
LongRunningOperation2();
}).start();
Thread thread3 = new Thread(() -> {
LongRunningOperation3();
}).start();
Log.Info("completion message goes here.")
}

As comments are mentioning, the easiest is either calling join() on each of the 3 threads: thread1.join(); thread2.join(); thread3.join();
Or use a CountDownLatch though it is a touch more involved (but maybe more conceptually 'correct'):
latch = new CountDownLatch(3)
get each thread to do latch.countDown() after completing its task.
get the main thread to latch.await() - voila.

Instead of creating Threads manually it is much better to use ExecutorService API. Using ExecutorService you can submit long running operations and as result you will receive Future instance which will let you wait until operation will be completed.
See below example which shows the idea:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class Threads {
public static void main(String[] args) {
new Threads().myMethod();
}
private String myMethod() {
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Future<?>> futures = new ArrayList<>(3);
futures.add(executor.submit(this::LongRunningOperation1));
futures.add(executor.submit(this::LongRunningOperation2));
futures.add(executor.submit(this::LongRunningOperation3));
for (Future<?> future : futures) {
try {
future.get();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("All operations are finished!");
return "Done";
}
private void LongRunningOperation1() {
sleep(TimeUnit.SECONDS.toMillis(1));
System.out.println("LongRunningOperation1 is finished!");
}
private void LongRunningOperation2() {
sleep(TimeUnit.SECONDS.toMillis(2));
System.out.println("LongRunningOperation2 is finished!");
}
private void LongRunningOperation3() {
sleep(TimeUnit.SECONDS.toMillis(3));
System.out.println("LongRunningOperation3 is finished!");
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Above code prints:
LongRunningOperation1 is finished!
LongRunningOperation2 is finished!
LongRunningOperation3 is finished!
All operations are finished!

Related

Different outputs each time this synchronized multithread program is run(Java.)

class Callme{
synchronized void call(String msg){
System.out.print(msg);
try{
Thread.sleep(500);
System.out.println("message");
}catch(InterruptedException e){
System.out.println(e);
}
}
}
class Caller implements Runnable{
String message;
Thread t;
Callme target;
Caller(Callme target, String msg){
t = new Thread(this);
this.target = target;
message = msg;
t.start();
}
public void run(){
target.call(message);
}
}
class Synch{
public static void main(String args[]){
Callme c = new Callme();
Caller ob1 = new Caller(c,"1");
Caller ob2 = new Caller(c,"2");
Caller ob3 = new Caller(c,"3");
try{
ob1.t.join();
ob2.t.join();
ob3.t.join();
}catch(InterruptedException e){
System.out.println(e);
}
}
}
I am new to Java. I tried this sample program while learning about synchronization in threads. The first time I ran it, it gave me the expected output.
1message
2message
3message
But as I started running it repeatedly, the order changed. Like:
1message
3message
2message
Why does this happen? Shouldn't the threads enter call() in the specified order(i.e ob1,ob2,ob3)?
The reason you get output in random order is because the threads are running parallel and any of them could reach the synchronized block first, so they could print in any order.
If you want to get results in a defined order then you could use a Callable<String> instead of a Runnable and have it return the string you compute in the thread, then use the Futures of the tasks you submitted and get the results in your submission order. I added a timestamp to show that the later tasks sometimes still complete first, since they're all running parallel, but all the processing in CallMe.call(String) is still synchronized and thread safe-ish.
Using Callables and Futures lets you still get the benefits of parallelism and also gives you control when processing the results.
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
...
public static void main(String args[]) {
ExecutorService executor = Executors.newFixedThreadPool(3);
CallMe c = new CallMe();
List<Future<String>> futures = new ArrayList<>();
futures.add(executor.submit(new Caller(c, "1")));
futures.add(executor.submit(new Caller(c, "2")));
futures.add(executor.submit(new Caller(c, "3")));
try {
for (Future<String> future : futures) {
System.out.println(future.get());
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
class Caller implements Callable<String> {
private String message;
private CallMe target;
Caller(CallMe target, String msg) {
this.target = target;
this.message = msg;
}
#Override public String call() {
return target.call(message);
}
}
class CallMe {
synchronized String call(String msg) {
try {
Thread.sleep(500);
return "message:" + msg + " - completed at system time " + new Timestamp(System.currentTimeMillis());
} catch (InterruptedException e) {
System.out.println(e);
return "error:" + e.getMessage();
}
}
}
For me it's:
3message
2message
1message
Why?
Because we started 3 threads that run concurrently.
Once we started the threads, the OS should give them CPU time. The first thread that arrives at the synchronized block will print to screen, the others will wait for it to finish, and so on.
If you want the printing to be pre-defined, then you should do:
Caller ob1 = new Caller(c,"1");
ob1.t.join();
Caller ob2 = new Caller(c,"2");
ob2.t.join();
Caller ob3 = new Caller(c,"3");
ob3.t.join();
But in most use-cases, you wouldn't do that, and instead don't use threads.
The synchronized keyword does not what you think it does. It simply protects the method, so only one thread can access it at a time. Therefore, the next number ("1", "2" or "3") can only be seen after "message" has been sent. The order of the threads, however, is not defined. Think about it like this: You basically call the methods at the same time (approximately). The JVM will spawn three threads that all begin execution immediately. One thread (always the first one) will call the method call and lock it so no other thread may access it. Now there are two threads waiting until call has finished so that they may use the method. The order in which they will call that method is completely arbitrary.

ArrayBlockingQueue NoSuchElementException

Just for learning, I have written the following code for custom thread pool referring and editing the code shown here.
As shown in the code I am using ArrayBlockingQueue for task queue.
Code:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class ThreadPoolService {
private final BlockingQueue<Runnable> taskQueue;
private final int corePoolSize;
private ThreadPoolService(int corePoolSize) {
this.corePoolSize = corePoolSize;
this.taskQueue = new ArrayBlockingQueue<>(corePoolSize);
ThreadPool[] threadPool = new ThreadPool[corePoolSize];
for (int i = 0; i < corePoolSize; i++) {
threadPool[i] = new ThreadPool();
threadPool[i].start();
}
}
public static ThreadPoolService newFixedThreadPool(int size) {
return new ThreadPoolService(size);
}
public void execute(Runnable task) {
try {
taskQueue.offer(task, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class ThreadPool extends Thread {
Runnable task;
#Override
public void run() {
while (true) {
try {
while (!taskQueue.isEmpty()) {
task = taskQueue.remove();
task.run();
}
} catch (RuntimeException ex) {
ex.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ThreadPoolService pool = ThreadPoolService.newFixedThreadPool(10);
Runnable task1 = () -> {
System.out.println(" Wait for sometime: -> " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Runnable task2 = () -> System.out.println(" Do Task 2 -> " + Thread.currentThread().getName());
Runnable task3 = () -> System.out.println(" Do Task 3 -> " + Thread.currentThread().getName());
Runnable task4 = () -> System.out.println(" Do Task 4 -> " + Thread.currentThread().getName());
List<Runnable> taskList = new ArrayList<>();
taskList.add(task1);
taskList.add(task2);
taskList.add(task3);
taskList.add(task4);
for (Runnable task : taskList) {
pool.execute(task);
}
}
}
This code runs fine sometimes and sometimes gives an error.
Success output:
Do Task 2 -> Thread-2
Wait for sometime: -> Thread-8
Do Task 3 -> Thread-6
Do Task 4 -> Thread-7
Failure output:
Do Task 4 -> Thread-3
Do Task 3 -> Thread-6
Wait for sometime: -> Thread-4
Do Task 2 -> Thread-7
java.util.NoSuchElementException
at java.util.AbstractQueue.remove(AbstractQueue.java:117)
at com.interview.java.ThreadPoolService$ThreadPool.run(ThreadPoolService.java:43)
java.util.NoSuchElementException
at java.util.AbstractQueue.remove(AbstractQueue.java:117)
at com.interview.java.ThreadPoolService$ThreadPool.run(ThreadPoolService.java:43)
java.util.NoSuchElementException
at java.util.AbstractQueue.remove(AbstractQueue.java:117)
at com.interview.java.ThreadPoolService$ThreadPool.run(ThreadPoolService.java:43)
I see the reason for the error is the attempt to remove the element when the queue is empty. But it should not because i am doing queue empty check at line no 42 (while (!taskQueue.isEmpty())). What is wrong with code and also why it runs without error sometimes ?
Between the 'while' check and the actual removal, the queue could be modified by another Thread, possibly resulting in the error you mention. That's called a 'race condition'.
So in order to fix that you'll need a way to block the access to the queue by other threads, either by 'locking', using a 'synchronized' block with a shared lock object. Or simply by 'polling' instead of removing.
BlockingQueue is thread-safe only on an individual operation level.I'm seeing check-then-actoperation in the code which is a compound operation which is not thread-safe. To make this code thread-safe perform the check-then-act inside a synchronized block and lock on the queue itself.
synchronized(taskQueue) {
while (!taskQueue.isEmpty()) {
task = taskQueue.remove();
task.run();
}};
optimization: If the task is a time consuming one, you can execute it outside the synchronized block. So that other threads don't have to wait till the current task completes.
What is wrong with code?
You access taskQueue field from several threads without synchronization. You must do queue empty check and remove operation atomically, which can be done with synchronized keyword:
private class ThreadPool extends Thread {
#Override
public void run() {
Runnable task;
while (true) {
synchronized(queue) {
// give access to taskQueue to one thread at a time
if (!taskQueue.isEmpty()) {
task = taskQueue.remove();
}
}
try {
task.run();
} catch (RuntimeException ex) {
ex.printStackTrace();
}
}
}
}
why it runs without error sometimes?
Because of nature of JVM thread scheduler: sometimes it plans thread execution in such a way that they access taskQueue synchronously by themselves. But when you deal with multithreading, you can't rely on thread execution order, and must synchronize access to shared objects by yourself.

Latch for different task types

I am looking for a java concurrency solution to the following problem.
There are some tasks being run, and a section of code C.
C must wait for all tasks to complete. (With a timeout)
No tasks may commence until C has finished.
I have looked through the java.concurrency package and I found a few things of interest, but nothing seems to work quite right:
Phasers would allow one way blocking, but not two way.
Semaphores, ForkJoinTasks and others have counter-type features but none seem to do what I want.
I believe I could construct something using a phaser and a lock like so:
void C() {
synchronized(lock) {
phaser.awaitAdvanceInterruptibly(phase, 1, TimeUnit.SECONDS);
// Start work anyway if a task is taking too long.
doWork();
}
}
void someTask() {
synchronized(lock) {
phaser.register();
}
doTask().thenRun(
() -> phaser.arriveAndDeregister()
);
}
Now while I'm fairly sure this would work, I'm also aware its a bad idea to try to build your own concurrency solution. Is there a better way of doing this?
If there isn't, what would I use for the phase argument?
Edit: This problem is within a project involving a web client connection, and therefore the tasks arrive unpredictably. However, it is possible that this situation could be avoided by more careful design.
This being a specialized use case, I think we'll need to use multiple concurrency utilities for co-ordination. The below program should do it. Please feel free to post questions of any parts aren't clear -
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class TestClass {
private volatile int numOfActiveTasks = 0;
private Semaphore cSemaphore = new Semaphore(1);
private Semaphore taskSemaphore = new Semaphore(1);
private Object tasksLock = new Object();
//Test method
public static void main(String[] args) throws IOException {
TestClass testClass = new TestClass();
//Launch some task threads
ExecutorService taskES = Executors.newFixedThreadPool(2);
IntStream.range(1, 11).forEach((i) -> taskES.submit(() -> {
try {
testClass.executeTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
//Launch some C threads
ExecutorService cES = Executors.newFixedThreadPool(2);
IntStream.range(1, 5).forEach((i) -> cES.submit(() -> {
try {
testClass.C();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
taskES.shutdown();
cES.shutdown();
}
void C() throws InterruptedException {
try {
cSemaphore.acquire();
//If tasks are running, wait at-least n seconds
this.taskSemaphore.tryAcquire(1, TimeUnit.SECONDS);
print("C started running");
doCsWork();
} finally {
cSemaphore.release();
print("C stopped running");
}
}
void executeTask() throws InterruptedException {
//Do not start while C is running
cSemaphore.acquire();
cSemaphore.release();
synchronized (tasksLock) {
++numOfActiveTasks;
taskSemaphore.tryAcquire();
print("A task started running. Total " + numOfActiveTasks + " tasks running");
}
doTasksWork();
synchronized (tasksLock) {
--numOfActiveTasks;
if (numOfActiveTasks == 0) {
taskSemaphore.release();
}
print("A task stopped running. Total " + numOfActiveTasks + " tasks remaining");
}
}
void doCsWork() throws InterruptedException {
Thread.sleep(1000);
}
void doTasksWork() throws InterruptedException {
Thread.sleep(2000);
}
void print(String message) {
System.out.println(message);
}
}
I found a solution for this problem in java.util.concurrent.locks, which is perfect for my use case.
StampedLock lock;
void C() {
long stamp = lock.tryWriteLock(1, TimeUnit.SECONDS);
doWork();
lock.unlockWrite(stamp);
}
void someTask() {
long stamp = lock.readLock();
doTask().thenRun(() -> lock.unlockRead(stamp));
}
The key with the StampedLock class is that the readLock() is not exclusive, whereas the writeLock() is exclusive. It also supports timeouts, similar to the regular Lock.

Java ExecutorService - why does this program keep running?

I'm trying to build something like a background task executor which terminates background tasks after a certain time if there's no answer (background tasks call webservices and they can time-out but I need to make sure they time out under a certain time)
So I have this as an experiment but if I run this the program does not terminate. I wonder if its because a background thread is still active maybe? How can I shut this down?
public class Test {
public static class Task implements Callable<Object> {
#Override
public Object call() throws Exception {
while(true) {}
}
}
public static void main(String[] args) {
try {
Task t = new Task();
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(t), 5L, TimeUnit.SECONDS);
executor.shutdown();
System.out.println("DONE");
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The ExecutorService does not kill the running threads, and since threads are created as non-daemon, the JVM doesn't exit.
What happens is that when timeout expires, futures returned by invokeAll() are cancelled, which means that a flag is set on the future object and you get a CancellationException if you try to call future.get(). However neither invokeAll(), nor shutdown() (or shutdownNow()) do anything to kill the thread.
Note that you cannot even kill threads yourself. All you can do is setting some application-specific flag or call Thread.interrupt(), but even that does not guarantee that the thread terminates.
There is a great post by Winterbe on how executors work. This is an excerpt from his tutorial
So basically executors always keep listening to the new tasks or callables/runnables and one way to shutdown the executor or stop the executor from listening is to interrupt whatever task it is executing. One way to do is calling the future.get() which stops when the main thread , suspends it and makes sure that the current thread gets executed completely before handing over the resource to other thread
You could probably have a higher number of threads and write your code to shutdown gracefully in the InterruptedException block
Here is a sample code that I've written and tested:
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecutorTest {
public static void main(String[] args) {
ExecutorService service = Executors.newWorkStealingPool(10);
Callable<AccountClass> newInstance = () -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
};
// for now only one instance is added to the list
// List<Callable<AccountClass>> callablesSingleList = Arrays.asList(newInstance);
// adding multipleCallalbes
List<Callable<AccountClass>> callablesMultipleList = Arrays.asList(
() -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
},
() -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
},
() -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
});
try {
service.invokeAll(callablesMultipleList).stream().map(future -> {
AccountClass fuClass = null;
try {
fuClass = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return fuClass;
}).forEach(getValue -> {
System.out.println("retunred value:" + getValue);
});
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
private static AccountClass getAcc(long itr) {
// probably call DB for every new thread iterator
System.out.println("getting the current thread" + itr);
AccountClass ac = new AccountClass();
ac.setId(itr);
ac.setName("vv");
ac.setRole("admin");
System.out.println("sending the accnt class:" + ac);
return ac;
}
}
UPDATE:
Another way of shutting down the executor is using the service.shutDownNow() - > which shutdowns the program even if its the middle of execution. You could use awaitTermination method to specify if you feel that it might take a few minutes to complete execution and then probably shutdown the service
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ExecutorScheduleFixedRate {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
Runnable task = () -> {
getAcc(33);
};
service.scheduleWithFixedDelay(task, 10, 5, TimeUnit.SECONDS);
if (!service.isShutdown()) {
List<Runnable> list2 = service.shutdownNow();
System.out.println(list2);
System.out.println("is shutdonw" + service.isShutdown());
System.out.println("Do something after the thread execution");
}
}
private static AccountClass getAcc(long itr) {
// probably call DB for every new thread iterator
System.out.println("getting the current thread" + itr);
AccountClass ac = new AccountClass();
ac.setId(itr);
ac.setName("vv");
ac.setRole("admin");
System.out.println("sending the accnt class:" + ac);
return ac;
}
}

How to timeout a thread

I want to run a thread for some fixed amount of time. If it is not completed within that time, I want to either kill it, throw some exception, or handle it in some way. How can it be done?
One way of doing it as I figured out from this thread
is to use a TimerTask inside the run() method of the Thread.
Are there any better solutions for this?
EDIT: Adding a bounty as I needed a clearer answer. The ExecutorService code given below does not address my problem. Why should I sleep() after executing (some code - I have no handle over this piece of code)? If the code is completed and the sleep() is interrupted, how can that be a timeOut?
The task that needs to be executed is not in my control. It can be any piece of code. The problem is this piece of code might run into an infinite loop. I don't want that to happen. So, I just want to run that task in a separate thread. The parent thread has to wait till that thread finishes and needs to know the status of the task (i.e whether it timed out or some exception occured or if its a success). If the task goes into an infinite loop, my parent thread keeps on waiting indefinitely, which is not an ideal situation.
Indeed rather use ExecutorService instead of Timer, here's an SSCCE:
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
#Override
public String call() throws Exception {
Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
return "Ready!";
}
}
Play a bit with the timeout argument in Future#get() method, e.g. increase it to 5 and you'll see that the thread finishes. You can intercept the timeout in the catch (TimeoutException e) block.
Update: to clarify a conceptual misunderstanding, the sleep() is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep(). Inside your long running task, you should be checking if the thread is not interrupted as follows:
while (!Thread.interrupted()) {
// Do your long running task here.
}
There isn't a 100% reliable way to do this for any old task. The task has to be written with this ability in mind.
Core Java libraries like ExecutorService cancel asynchronous tasks with interrupt() calls on the worker thread. So, for example, if the task contains some sort of loop, you should be checking its interrupt status on each iteration. If the task is doing I/O operations, they should be interruptible too—and setting that up can be tricky. In any case, keep in mind that code has to actively check for interrupts; setting an interrupt doesn't necessarily do anything.
Of course, if your task is some simple loop, you can just check the current time at each iteration and give up when a specified timeout has elapsed. A worker thread isn't needed in that case.
Consider using an instance of ExecutorService. Both invokeAll() and invokeAny() methods are available with a timeout parameter.
The current thread will block until the method completes (not sure if this is desirable) either because the task(s) completed normally or the timeout was reached. You can inspect the returned Future(s) to determine what happened.
Assuming the thread code is out of your control:
From the Java documentation mentioned above:
What if a thread doesn't respond to Thread.interrupt?
In some cases, you can use application specific tricks. For example,
if a thread is waiting on a known socket, you can close the socket to
cause the thread to return immediately. Unfortunately, there really
isn't any technique that works in general. It should be noted that in
all situations where a waiting thread doesn't respond to
Thread.interrupt, it wouldn't respond to Thread.stop either. Such
cases include deliberate denial-of-service attacks, and I/O operations
for which thread.stop and thread.interrupt do not work properly.
Bottom Line:
Make sure all threads can be interrupted, or else you need specific knowledge of the thread - like having a flag to set. Maybe you can require that the task be given to you along with the code needed to stop it - define an interface with a stop() method. You can also warn when you failed to stop a task.
BalusC said:
Update: to clarify a conceptual misunderstanding, the sleep() is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep().
But if you replace Thread.sleep(4000); with for (int i = 0; i < 5E8; i++) {} then it doesn't compile, because the empty loop doesn't throw an InterruptedException.
And for the thread to be interruptible, it needs to throw an InterruptedException.
This seems like a serious problem to me. I can't see how to adapt this answer to work with a general long-running task.
Edited to add: I reasked this as a new question: [ interrupting a thread after fixed time, does it have to throw InterruptedException? ]
I created a helper class just for this some time ago. Works great:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* TimeOut class - used for stopping a thread that is taking too long
* #author Peter Goransson
*
*/
public class TimeOut {
Thread interrupter;
Thread target;
long timeout;
boolean success;
boolean forceStop;
CyclicBarrier barrier;
/**
*
* #param target The Runnable target to be executed
* #param timeout The time in milliseconds before target will be interrupted or stopped
* #param forceStop If true, will Thread.stop() this target instead of just interrupt()
*/
public TimeOut(Runnable target, long timeout, boolean forceStop) {
this.timeout = timeout;
this.forceStop = forceStop;
this.target = new Thread(target);
this.interrupter = new Thread(new Interrupter());
barrier = new CyclicBarrier(2); // There will always be just 2 threads waiting on this barrier
}
public boolean execute() throws InterruptedException {
// Start target and interrupter
target.start();
interrupter.start();
// Wait for target to finish or be interrupted by interrupter
target.join();
interrupter.interrupt(); // stop the interrupter
try {
barrier.await(); // Need to wait on this barrier to make sure status is set
} catch (BrokenBarrierException e) {
// Something horrible happened, assume we failed
success = false;
}
return success; // status is set in the Interrupter inner class
}
private class Interrupter implements Runnable {
Interrupter() {}
public void run() {
try {
Thread.sleep(timeout); // Wait for timeout period and then kill this target
if (forceStop) {
target.stop(); // Need to use stop instead of interrupt since we're trying to kill this thread
}
else {
target.interrupt(); // Gracefully interrupt the waiting thread
}
System.out.println("done");
success = false;
} catch (InterruptedException e) {
success = true;
}
try {
barrier.await(); // Need to wait on this barrier
} catch (InterruptedException e) {
// If the Child and Interrupter finish at the exact same millisecond we'll get here
// In this weird case assume it failed
success = false;
}
catch (BrokenBarrierException e) {
// Something horrible happened, assume we failed
success = false;
}
}
}
}
It is called like this:
long timeout = 10000; // number of milliseconds before timeout
TimeOut t = new TimeOut(new PhotoProcessor(filePath, params), timeout, true);
try {
boolean sucess = t.execute(); // Will return false if this times out
if (!sucess) {
// This thread timed out
}
else {
// This thread ran completely and did not timeout
}
} catch (InterruptedException e) {}
I think you should take a look at proper concurrency handling mechanisms (threads running into infinite loops doesn't sound good per se, btw). Make sure you read a little about the "killing" or "stopping" Threads topic.
What you are describing,sound very much like a "rendezvous", so you may want to take a look at the CyclicBarrier.
There may be other constructs (like using CountDownLatch for example) that can resolve your problem (one thread waiting with a timeout for the latch, the other should count down the latch if it has done it's work, which would release your first thread either after a timeout or when the latch countdown is invoked).
I usually recommend two books in this area: Concurrent Programming in Java and Java Concurrency in Practice.
In the solution given by BalusC, the main thread will stay blocked for the timeout period. If you have a thread pool with more than one thread, you will need the same number of additional thread that will be using Future.get(long timeout,TimeUnit unit) blocking call to wait and close the thread if it exceeds the timeout period.
A generic solution to this problem is to create a ThreadPoolExecutor Decorator that can add the timeout functionality. This Decorator class should create as many threads as ThreadPoolExecutor has, and all these threads should be used only to wait and close the ThreadPoolExecutor.
The generic class should be implemented like below:
import java.util.List;
import java.util.concurrent.*;
public class TimeoutThreadPoolDecorator extends ThreadPoolExecutor {
private final ThreadPoolExecutor commandThreadpool;
private final long timeout;
private final TimeUnit unit;
public TimeoutThreadPoolDecorator(ThreadPoolExecutor threadpool,
long timeout,
TimeUnit unit ){
super( threadpool.getCorePoolSize(),
threadpool.getMaximumPoolSize(),
threadpool.getKeepAliveTime(TimeUnit.MILLISECONDS),
TimeUnit.MILLISECONDS,
threadpool.getQueue());
this.commandThreadpool = threadpool;
this.timeout=timeout;
this.unit=unit;
}
#Override
public void execute(Runnable command) {
super.execute(() -> {
Future<?> future = commandThreadpool.submit(command);
try {
future.get(timeout, unit);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException | TimeoutException e) {
throw new RejectedExecutionException(e);
} finally {
future.cancel(true);
}
});
}
#Override
public void setCorePoolSize(int corePoolSize) {
super.setCorePoolSize(corePoolSize);
commandThreadpool.setCorePoolSize(corePoolSize);
}
#Override
public void setThreadFactory(ThreadFactory threadFactory) {
super.setThreadFactory(threadFactory);
commandThreadpool.setThreadFactory(threadFactory);
}
#Override
public void setMaximumPoolSize(int maximumPoolSize) {
super.setMaximumPoolSize(maximumPoolSize);
commandThreadpool.setMaximumPoolSize(maximumPoolSize);
}
#Override
public void setKeepAliveTime(long time, TimeUnit unit) {
super.setKeepAliveTime(time, unit);
commandThreadpool.setKeepAliveTime(time, unit);
}
#Override
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
super.setRejectedExecutionHandler(handler);
commandThreadpool.setRejectedExecutionHandler(handler);
}
#Override
public List<Runnable> shutdownNow() {
List<Runnable> taskList = super.shutdownNow();
taskList.addAll(commandThreadpool.shutdownNow());
return taskList;
}
#Override
public void shutdown() {
super.shutdown();
commandThreadpool.shutdown();
}
}
The above decorator can be used as below:
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args){
long timeout = 2000;
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 10, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<>(true));
threadPool = new TimeoutThreadPoolDecorator( threadPool ,
timeout,
TimeUnit.MILLISECONDS);
threadPool.execute(command(1000));
threadPool.execute(command(1500));
threadPool.execute(command(2100));
threadPool.execute(command(2001));
while(threadPool.getActiveCount()>0);
threadPool.shutdown();
}
private static Runnable command(int i) {
return () -> {
System.out.println("Running Thread:"+Thread.currentThread().getName());
System.out.println("Starting command with sleep:"+i);
try {
Thread.sleep(i);
} catch (InterruptedException e) {
System.out.println("Thread "+Thread.currentThread().getName()+" with sleep of "+i+" is Interrupted!!!");
return;
}
System.out.println("Completing Thread "+Thread.currentThread().getName()+" after sleep of "+i);
};
}
}
I post you a piece of code which show a way how to solve the problem.
As exemple I'm reading a file.
You could use this method for another operation, but you need to implements the kill() method so that the main operation will be interrupted.
hope it helps
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* Main class
*
* #author el
*
*/
public class Main {
/**
* Thread which perform the task which should be timed out.
*
* #author el
*
*/
public static class MainThread extends Thread {
/**
* For example reading a file. File to read.
*/
final private File fileToRead;
/**
* InputStream from the file.
*/
final private InputStream myInputStream;
/**
* Thread for timeout.
*/
final private TimeOutThread timeOutThread;
/**
* true if the thread has not ended.
*/
boolean isRunning = true;
/**
* true if all tasks where done.
*/
boolean everythingDone = false;
/**
* if every thing could not be done, an {#link Exception} may have
* Happens.
*/
Throwable endedWithException = null;
/**
* Constructor.
*
* #param file
* #throws FileNotFoundException
*/
MainThread(File file) throws FileNotFoundException {
setDaemon(false);
fileToRead = file;
// open the file stream.
myInputStream = new FileInputStream(fileToRead);
// Instantiate the timeout thread.
timeOutThread = new TimeOutThread(10000, this);
}
/**
* Used by the {#link TimeOutThread}.
*/
public void kill() {
if (isRunning) {
isRunning = false;
if (myInputStream != null) {
try {
// close the stream, it may be the problem.
myInputStream.close();
} catch (IOException e) {
// Not interesting
System.out.println(e.toString());
}
}
synchronized (this) {
notify();
}
}
}
/**
* The task which should be timed out.
*/
#Override
public void run() {
timeOutThread.start();
int bytes = 0;
try {
// do something
while (myInputStream.read() >= 0) {
// may block the thread.
myInputStream.read();
bytes++;
// simulate a slow stream.
synchronized (this) {
wait(10);
}
}
everythingDone = true;
} catch (IOException e) {
endedWithException = e;
} catch (InterruptedException e) {
endedWithException = e;
} finally {
timeOutThread.kill();
System.out.println("-->read " + bytes + " bytes.");
isRunning = false;
synchronized (this) {
notifyAll();
}
}
}
}
/**
* Timeout Thread. Kill the main task if necessary.
*
* #author el
*
*/
public static class TimeOutThread extends Thread {
final long timeout;
final MainThread controlledObj;
TimeOutThread(long timeout, MainThread controlledObj) {
setDaemon(true);
this.timeout = timeout;
this.controlledObj = controlledObj;
}
boolean isRunning = true;
/**
* If we done need the {#link TimeOutThread} thread, we may kill it.
*/
public void kill() {
isRunning = false;
synchronized (this) {
notify();
}
}
/**
*
*/
#Override
public void run() {
long deltaT = 0l;
try {
long start = System.currentTimeMillis();
while (isRunning && deltaT < timeout) {
synchronized (this) {
wait(Math.max(100, timeout - deltaT));
}
deltaT = System.currentTimeMillis() - start;
}
} catch (InterruptedException e) {
// If the thread is interrupted,
// you may not want to kill the main thread,
// but probably yes.
} finally {
isRunning = false;
}
controlledObj.kill();
}
}
/**
* Start the main task and wait for the end.
*
* #param args
* #throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
long start = System.currentTimeMillis();
MainThread main = new MainThread(new File(args[0]));
main.start();
try {
while (main.isRunning) {
synchronized (main) {
main.wait(1000);
}
}
long stop = System.currentTimeMillis();
if (main.everythingDone)
System.out.println("all done in " + (stop - start) + " ms.");
else {
System.out.println("could not do everything in "
+ (stop - start) + " ms.");
if (main.endedWithException != null)
main.endedWithException.printStackTrace();
}
} catch (InterruptedException e) {
System.out.println("You've killed me!");
}
}
}
Regards
Here is my really simple to use helper class to run or call piece of Java code :-)
This is based on the excellent answer from BalusC
package com.mycompany.util.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Calling {#link Callable#call()} or Running {#link Runnable#run()} code
* with a timeout based on {#link Future#get(long, TimeUnit))}
* #author pascaldalfarra
*
*/
public class CallableHelper
{
private CallableHelper()
{
}
public static final void run(final Runnable runnable, int timeoutInSeconds)
{
run(runnable, null, timeoutInSeconds);
}
public static final void run(final Runnable runnable, Runnable timeoutCallback, int timeoutInSeconds)
{
call(new Callable<Void>()
{
#Override
public Void call() throws Exception
{
runnable.run();
return null;
}
}, timeoutCallback, timeoutInSeconds);
}
public static final <T> T call(final Callable<T> callable, int timeoutInSeconds)
{
return call(callable, null, timeoutInSeconds);
}
public static final <T> T call(final Callable<T> callable, Runnable timeoutCallback, int timeoutInSeconds)
{
ExecutorService executor = Executors.newSingleThreadExecutor();
try
{
Future<T> future = executor.submit(callable);
T result = future.get(timeoutInSeconds, TimeUnit.SECONDS);
System.out.println("CallableHelper - Finished!");
return result;
}
catch (TimeoutException e)
{
System.out.println("CallableHelper - TimeoutException!");
if(timeoutCallback != null)
{
timeoutCallback.run();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
finally
{
executor.shutdownNow();
executor = null;
}
return null;
}
}
The following snippet will start an operation in a separate thread, then wait for up to 10 seconds for the operation to complete. If the operation does not complete in time, the code will attempt to cancel the operation, then continue on its merry way. Even if the operation cannot be cancelled easily, the parent thread will not wait for the child thread to terminate.
ExecutorService executorService = getExecutorService();
Future<SomeClass> future = executorService.submit(new Callable<SomeClass>() {
public SomeClass call() {
// Perform long-running task, return result. The code should check
// interrupt status regularly, to facilitate cancellation.
}
});
try {
// Real life code should define the timeout as a constant or
// retrieve it from configuration
SomeClass result = future.get(10, TimeUnit.SECONDS);
// Do something with the result
} catch (TimeoutException e) {
future.cancel(true);
// Perform other error handling, e.g. logging, throwing an exception
}
The getExecutorService() method can be implemented in a number of ways. If you do not have any particular requirements, you can simply call Executors.newCachedThreadPool() for thread pooling with no upper limit on the number of threads.
One thing that I've not seen mentioned is that killing threads is generally a Bad Idea. There are techniques for making threaded methods cleanly abortable, but that's different to just killing a thread after a timeout.
The risk with what you're suggesting is that you probably don't know what state the thread will be in when you kill it - so you risk introducing instability. A better solution is to make sure your threaded code either doesn't hang itself, or will respond nicely to an abort request.
Great answer by BalusC's:
but Just to add that the timeout itself does not interrupt the thread itself. even if you are checking with while(!Thread.interrupted()) in your task. if you want to make sure thread is stopped you should also make sure future.cancel() is invoked when timeout exception is catch.
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
//Without the below cancel the thread will continue to live
// even though the timeout exception thrown.
future.cancel();
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
#Override
public String call() throws Exception {
while(!Thread.currentThread.isInterrupted()){
System.out.println("Im still running baby!!");
}
}
}
I think the answer mainly depends on the task itself.
Is it doing one task over and over again?
Is it necessary that the timeout interrupts a currently running task immediately after it expires?
If the first answer is yes and the second is no, you could keep it as simple as this:
public class Main {
private static final class TimeoutTask extends Thread {
private final long _timeoutMs;
private Runnable _runnable;
private TimeoutTask(long timeoutMs, Runnable runnable) {
_timeoutMs = timeoutMs;
_runnable = runnable;
}
#Override
public void run() {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() < (start + _timeoutMs)) {
_runnable.run();
}
System.out.println("execution took " + (System.currentTimeMillis() - start) +" ms");
}
}
public static void main(String[] args) throws Exception {
new TimeoutTask(2000L, new Runnable() {
#Override
public void run() {
System.out.println("doing something ...");
try {
// pretend it's taking somewhat longer than it really does
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
}
}
If this isn't an option, please narrow your requirements - or show some code.
I was looking for an ExecutorService that can interrupt all timed out Runnables executed by it, but found none. After a few hours I created one as below. This class can be modified to enhance robustness.
public class TimedExecutorService extends ThreadPoolExecutor {
long timeout;
public TimedExecutorService(int numThreads, long timeout, TimeUnit unit) {
super(numThreads, numThreads, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(numThreads + 1));
this.timeout = unit.toMillis(timeout);
}
#Override
protected void beforeExecute(Thread thread, Runnable runnable) {
Thread interruptionThread = new Thread(new Runnable() {
#Override
public void run() {
try {
// Wait until timeout and interrupt this thread
Thread.sleep(timeout);
System.out.println("The runnable times out.");
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
interruptionThread.start();
}
}
Usage:
public static void main(String[] args) {
Runnable abcdRunnable = new Runnable() {
#Override
public void run() {
System.out.println("abcdRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("abcdRunnable ended");
}
};
Runnable xyzwRunnable = new Runnable() {
#Override
public void run() {
System.out.println("xyzwRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("xyzwRunnable ended");
}
};
int numThreads = 2, timeout = 5;
ExecutorService timedExecutor = new TimedExecutorService(numThreads, timeout, TimeUnit.SECONDS);
timedExecutor.execute(abcdRunnable);
timedExecutor.execute(xyzwRunnable);
timedExecutor.shutdown();
}
Now , l meet a issue like this. It happens to decode picture. The process of decode takes too much time that the screen keep black. l add a time controler: when the time is too long, then pop up from the current Thread.
The following is the diff:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Bitmap> future = executor.submit(new Callable<Bitmap>() {
#Override
public Bitmap call() throws Exception {
Bitmap bitmap = decodeAndScaleBitmapFromStream(context, inputUri);// do some time consuming operation
return null;
}
});
try {
Bitmap result = future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e){
future.cancel(true);
}
executor.shutdown();
return (bitmap!= null);
I had the same problem. So i came up with a simple solution like this.
public class TimeoutBlock {
private final long timeoutMilliSeconds;
private long timeoutInteval=100;
public TimeoutBlock(long timeoutMilliSeconds){
this.timeoutMilliSeconds=timeoutMilliSeconds;
}
public void addBlock(Runnable runnable) throws Throwable{
long collectIntervals=0;
Thread timeoutWorker=new Thread(runnable);
timeoutWorker.start();
do{
if(collectIntervals>=this.timeoutMilliSeconds){
timeoutWorker.stop();
throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated.");
}
collectIntervals+=timeoutInteval;
Thread.sleep(timeoutInteval);
}while(timeoutWorker.isAlive());
System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds.");
}
/**
* #return the timeoutInteval
*/
public long getTimeoutInteval() {
return timeoutInteval;
}
/**
* #param timeoutInteval the timeoutInteval to set
*/
public void setTimeoutInteval(long timeoutInteval) {
this.timeoutInteval = timeoutInteval;
}
}
Guarantees that if block didn't execute within the time limit. the process will terminate and throws an exception.
example :
try {
TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds
Runnable block=new Runnable() {
#Override
public void run() {
//TO DO write block of code
}
};
timeoutBlock.addBlock(block);// execute the runnable block
} catch (Throwable e) {
//catch the exception here . Which is block didn't execute within the time limit
}

Categories

Resources