Java - Timeout long running Callable Thread - java

public class FutureGetTimeoutTest {
private static final ExecutorService THREAD_POOL = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws InterruptedException, ExecutionException {
List<String> respList = new ArrayList<String>();
List<Future<String>> futures = new ArrayList<Future<String>>();
futures.add(THREAD_POOL.submit(new CallableTask(1L)));
futures.add(THREAD_POOL.submit(new CallableTask(2L)));
futures.add(THREAD_POOL.submit(new CallableTask(3L)));
long start = System.currentTimeMillis();
System.out.println(start);
for (Future<String> future : futures) {
try {
respList.add(future.get(10000, TimeUnit.MILLISECONDS));
/*
* Timeout time for 2nd Task starts only at the end of 1st Task Timeout
* and so 2nd task is able to run for 20s and 3rd task for 30s!
*/
} catch (TimeoutException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println(end);
System.out.println(end - start);
System.out.println(respList);
}
}
class CallableTask implements Callable<String> {
private long ipAddressL;
public CallableTask(long ipAddressL) {
this.ipAddressL = ipAddressL;
}
#Override
public String call() throws Exception {
if (ipAddressL == 1) {
Thread.sleep(10000);
/* Imagine a DB operation taking more time. */
return "1";
} else if (ipAddressL == 2) {
Thread.sleep(20000);
return "2";
} else {
Thread.sleep(30000);
return "3";
}
}
}
I want to return a empty string or just terminate the thread or throw a TimeoutException from within each task if each task takes more than 10 seconds individually.
Say 1st thread takes 10s, Future.get() will wait for 10s and then timeout. I will catch the exception and proceed the iteration for 2nd future object. Say 2nd thread is not completed by this time (which means it ran for 10s while 1st thread ran and is still running), now Future.get() on 2nd thread will wait for another 10s and so a total of 20s and so on for subsequent threads.
future.get(1000, TimeUnit.MILLISECONDS) (1 sec),
will ensure 10s limit for the whole operation but I need a 10s limit on the whole operation by having a 10s limit on each individual concurrent task.

Use THREAD_POOL.invokeAll instead of submit to wait 10s for the tasks to complete.
If some of the tasks have completed before 10 seconds pass, you can check for that with future.isDone() and retrieve the result without blocking using future.get.

Related

ForkJoinPool incorrect invokeAll method behavior (java)

ExecutorService have invokeAll method, and documentation say next:
Executes the given tasks, returning a list of Futures holding their
status and results when all complete or the timeout expires, whichever
happens first. Future.isDone is true for each element of the returned
list. Upon return, tasks that have not completed are cancelled. Note
that a completed task could have terminated either normally or by
throwing an exception. The results of this method are undefined if the
given collection is modified while this operation is in progress
Consider the following code:
public class Main {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<Integer>> tasks = Arrays.asList(
Main::veryLongCalculations,
Main::veryLongCalculations,
Main::veryLongCalculations);
try {
List<Future<Integer>> resultTasks = executorService.invokeAll(tasks, 2, TimeUnit.SECONDS);
for (Future<Integer> task: resultTasks) {
System.out.println("is done: " + task.isDone() + ", canceled: " + task.isCancelled());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static Integer veryLongCalculations() {
while (!Thread.currentThread().isInterrupted()) {
//very long calculations
}
System.out.println("interrupted");
return 0;
}
}
If we run this code, the following output will be displayed on the screen:
interrupted
interrupted
interrupted
is done: true, canceled: true
is done: true, canceled: true
is done: true, canceled: true
The tasks were clearly running longer than the timeout and so they were cancelled. Status of tasks is completed. Everything worked exactly as expected.
But if we use ForkJoinPool as ExecutorService (ExecutorService executorService = Executors.newWorkStealingPool()) then the output will be as like this:
interrupted
interrupted
is done: true, canceled: true
is done: true, canceled: true
is done: false, canceled: false
One of the tasks is never cancelled, which contradicts the documentation
But if we change sdk from java17 to java11, then it will work fine.
I began to understand and saw that ForkJoinPool inherits from the AbstractExecutorService class, which implements the invokeAll method. But in java 17 this method is overloaded in the ForkJoinPool itself. Here is the overloaded method:
#Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
try {
for (Callable<T> t : tasks) {
ForkJoinTask<T> f =
new ForkJoinTask.AdaptedInterruptibleCallable<T>(t);
futures.add(f);
externalSubmit(f);
}
long startTime = System.nanoTime(), ns = nanos;
boolean timedOut = (ns < 0L);
for (int i = futures.size() - 1; i >= 0; --i) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
if (timedOut)
ForkJoinTask.cancelIgnoringExceptions(f);
else {
((ForkJoinTask<T>)f).awaitPoolInvoke(this, ns);
if ((ns = nanos - (System.nanoTime() - startTime)) < 0L)
timedOut = true;
}
}
}
return futures;
} catch (Throwable t) {
for (Future<T> e : futures)
ForkJoinTask.cancelIgnoringExceptions(e);
throw t;
}
}
On the first iteration, the timedOut variable will always be false, so one task will never be cancelled. Is this a bug? Or is there some other reason why it works this way? This behavior is clearly contrary to the documentation, which says that all tasks should have a completed status and should be canceled if the timeout expires.

How can I create multithreaded code using ThreadpoolExecutor & Callable Future

I have an execute method which is running multiple test cases one by one, the test cases are passed in a list of Strings arrays.
I am trying to run this test cases in multi-threaded way, also writing data in CSV file in parallel.
Here is what I have done but it seems that the code is not working in a multithreaded way. I have passed nThread 2,5,7 in newFixedThreadPool() but it is taking the same time to execute the code.
private void executeTest(List<String[]> inputArray) throws ExecutionException, InterruptedException {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(nThreads);//2, 5, 7
long start = System.currentTimeMillis();
for (String[] listOfArray : inputArray) {
Callable c2 = new Callable() {
public ApiResponse call() {
response = runTestCase(listOfArray);
try {
csvWriter.writeCsv(listOfArray[0], response);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
};
System.out.println("nThread :"+nThreads);
Future<ApiResponse> result = executor.submit(c2);
result.get();
}
long stop = System.currentTimeMillis();
long timeTaken = stop - start;
System.out.println("Total time taken :"+timeTaken+"No of Theads :"+nThreads);
}
The call to future result.get(0) blocks until the action is completed, so you are just executing the tasks one by one inside your loop - even if they are actioned on different threads by the executor service.
// result.get();
Instead remove the line above and await termination at the end so that the full number of threads in your pool may receive tasks at same time, such as:
// All task submitted, mark for shutdown (only call after ALL submits done)
executor.shutdown();
// Wait for the executor service to finish
// You should consider how long this should be:
if (!executor.awaitTermination(whateverTimeIsReasonable, TimeUnit.SECONDS))
throw new RuntimeException("Test failed");
Tests that hiding exceptions are no help for testing, changing this:
e.printStackTrace();
to throw new UncheckedIOException(e); will ensure that all errors are reported.

How to make thread work in order and run many times? [duplicate]

This question already has answers here:
Execution order of multiple threads
(4 answers)
Closed 6 years ago.
I have 3 thread which i would like it to print in order but when I run the program it's keep getting result . I don't understand how it couldn't run thread in order. I would like to continue run thread 1 and 2 and 3 respectively. In each thread there is a loop for printing it's multiple times. So I would like to make the main thread to run each thread in order. This is my code.
threadMessage("Starting MessageLoop thread");
long patience =
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
Thread t2 = new Thread(new MessageLoop2());
Thread t3 = new Thread(new MessageLoop3());
t.setPriority(10);
t2.setPriority(5);
t3.setPriority(1);
t.start();
t2.start();
t3.start();
This is my thread function(3 threads)
private static class MessageLoop
implements Runnable {
public void run() {
try {
for(int i = 0;i<20;i++)
{
Thread.sleep(1000);
// Print a message
threadMessage("A");
}
} catch (InterruptedException e) {
threadMessage("thread interrupted");
}
}
}
private static class MessageLoop2
implements Runnable {
public void run() {
try {
for(int i = 0;i<20;i++)
{ Thread.sleep(1000);
// Print a message
threadMessage("B");
}
} catch (InterruptedException e) {
threadMessage("thread interrupted");
}
}
private static class MessageLoop3
implements Runnable {
public void run() {
String importantInfo = "E";
try {
for(int i = 0;i<20;i++)
{
Thread.sleep(1000);
// Print a message
threadMessage(importantInfo);
}
} catch (InterruptedException e) {
threadMessage("Thread interrupted");
}
}
And this is my code to make it run in order. I want to make my program run in order like this MessageLoop1 and 2 and 3 respectively.
while (t.isAlive()) {
threadMessage("Still waiting...");
t.join(2000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting!");
t.interrupt();
// Shouldn't be long now
// -- wait indefinitely
t.join();
}
while(t2.isAlive()){
threadMessage("Still waiting...");
t2.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t2.isAlive()) {
threadMessage("Tired of waiting!");
t2.interrupt();
// Shouldn't be long now
// -- wait indefinitely
t2.join();
}
}
while(t3.isAlive()){
threadMessage("Still waiting...");
t3.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t3.isAlive()) {
threadMessage("Tired of waiting!");
t3.interrupt();
// Shouldn't be long now
// -- wait indefinitely
t3.join();
}
}
}
But the result is coming like B,A,C. Can anyone explain this situation? And are my code wrong? Thank you!
That's how threads work. You don't get a guarantee at all which thread will finish first - and that's by design.
I assume what you want, is actually what the jdk calls a future and an ExecutorService.
(pseudocode - will have syntax errors)
ExecutorService s = Executors.newCachedThreadPool();
try {
Future f1 = s.submit(new MessageLoop());
Future f2 = s.submit(new MessageLoop2());
Future f3 = s.submit(new MessageLoop3());
f1.await(10, TimeUnit.SECONDS); // waits for the first thread to finish
// first thread finished now
f2.await(10, TimeUnit.SECONDS);
// second thread finished now
// ...
} finally { s.shutdown(); }
very important is to manage the proper shutdown of the ExecutorService, as the executor service will manage a couple of threads that run until you terminate them. if you don't shut it down, then your applicationo will not terminate.
What makes you assume you are controlling order?
The individual MessageLoop implementations are not blocked from executing in any way. So they just will run at the descretion of the thread scheduling.
You would need to introduce a shared ressource that takes the role of lock between the control thread (trying to enforce the order) and the worker threads.
In your current code the control thread just applies a special sequence on collecting the termination of the workers. That may have been executed and completed earlier in time.
If you are interested in a sequential execution and do not want to execute the tasks inline (same thread as your control), then you might just execute the threads in sequence to achieve your goal of sequential execution. (start each thread and wait for termination before starting another).
As you seam to have a restriction on the order of execution you would need some semaphore to coordinate such execution.

How to start two process at the same time and then wait both completed?

I want to start two process at the same time and make sure complete them all before proceeding other steps. Can you help? I already tried Thread, it can't start two at the same time and wait until been done.
final CyclicBarrier gate = new CyclicBarrier(3);
Thread r2 = new Thread()
{
public void run()
{
try
{
int i = 0;
while (i < 3)
{
System.out.println("Goodbye, " + "cruel world!");
Thread.sleep(2000L);
i++;
gate.await();
}
}
catch (InterruptedException | BrokenBarrierException iex)
{
}
}
};
Thread r3 = new Thread()
{
public void run()
{
try
{
int i = 0;
while (i < 3)
{
System.out.println("Goodbye, " + "cruel world!");
Thread.sleep(2000L);
i++;
gate.await();
}
}
catch (InterruptedException | BrokenBarrierException iex)
{
}
}
};
r2.start();
r3.start();
gate.await();
System.out.println("Donew");
You can use Thread.join()to wait until your subprocesses/threads have finished.
You should not need CyclicBarrier.
Your problem is that you are repeatedly waiting for three parties, but only two threads are calling await() repeatedly. I would expect your code to immediately print, "Goodbye, cruel world!" twice, and "Done", then hang, because the loops are waiting for a third thread to invoke await() again, but the main thread has now terminated.
One solution is for your main thread to loop, invoking await() the same number of times that your task does. But that would be kind of ugly.
I'd suggest using the invokeAll() method of an ExecutorService. This will submit your tasks to the service at (approximately) the same time, then block until all tasks complete. If you want to try to improve the simultaneity of the task commencing, you could add a CyclicBarrier, but it looks like you are more concerned with when the tasks end, and invokeAll() will take care of that for you.
final class Sample
implements Callable<Void>
{
private static final int ITERATIONS = 3;
private static final long AVG_TIME_MS = 2000;
public static void main(String[] args)
throws InterruptedException
{
List<Sample> tasks = Arrays.asList(new Sample(), new Sample());
ExecutorService workers = Executors.newFixedThreadPool(tasks.size());
for (int i = 1; i <= ITERATIONS; ++i) {
/* invokeAll() blocks until all tasks complete. */
List<Future<Void>> results = workers.invokeAll(tasks);
for (Future<?> result : results) {
try {
result.get();
}
catch (ExecutionException ex) {
ex.getCause().printStackTrace();
return;
}
}
System.out.printf("Completed iteration %d.%n", i);
}
workers.shutdown();
System.out.println("Done");
}
#Override
public Void call()
throws InterruptedException
{
/* The average wait time will be AVG_TIME_MS milliseconds. */
ThreadLocalRandom random = ThreadLocalRandom.current();
long wait = (long) (-AVG_TIME_MS * Math.log(1 - random.nextDouble()));
System.out.printf("Goodbye, cruel world! (Waiting %d ms)%n", wait);
Thread.sleep(wait);
return null;
}
}
Notice how I spiced things up with a random wait time. Yet, invokeAll() waits until all of tasks in that iteration complete.
It's impossible for the single processor machines.
Even if you find lot of answers on threads its not gonna start two process at the same time
If you accept the Relative Simultanity that will be easy.

Performance Improvement for each thread using different unique id

Problem Statement is:-
Each thread uses unique ID between 1 and 1000 and program has to run for 60 minutes or more, So in that 60 minutes it is possible that all the ID's will get finished so I need to reuse those ID's again,
I know several ways to do it, one way is the below that I wrote by taking help from StackOverflow, but when I tried running this, what I found is that, after few minutes of run this program gets very slow and it takes lot of time to print the ID on the console. And also I get OutOfMemory Error sometimes. Is there any better way to solve this kind of problem?
class IdPool {
private final LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
public IdPool() {
for (int i = 1; i <= 1000; i++) {
availableExistingIds.add(i);
}
}
public synchronized Integer getExistingId() {
return availableExistingIds.removeFirst();
}
public synchronized void releaseExistingId(Integer id) {
availableExistingIds.add(id);
}
}
class ThreadNewTask implements Runnable {
private IdPool idPool;
public ThreadNewTask(IdPool idPool) {
this.idPool = idPool;
}
public void run() {
Integer id = idPool.getExistingId();
someMethod(id);
idPool.releaseExistingId(id);
}
private void someMethod(Integer id) {
System.out.println("Task: " +id);
}
}
public class TestingPool {
public static void main(String[] args) throws InterruptedException {
int size = 10;
int durationOfRun = 60;
IdPool idPool = new IdPool();
// create thread pool with given size
// create thread pool with given size
ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
// queue some tasks
long startTime = System.currentTimeMillis();
long endTime = startTime + (durationOfRun * 60 * 1000L);
// Running it for 60 minutes
while(System.currentTimeMillis() <= endTime) {
service.submit(new ThreadNewTask(idPool));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
I already explained you in your previous question that your code submitted millions and millions of tasks to the executor, since it submits tasks in a loop during 60 minutes, withot waiting.
It's very unclear what your end goal is, but as is, you're filling a queue of tasks until you don't have any memory available anymore. Since you don't explain the goal of your program, it's hard to give you any solution.
But the first thing you could do is to limit the size of the task queue of your executor. This would force the main thread to block each time the queue is full.

Categories