How to shutdown an ExecutorService from one of its threads? - java

I want to stop the whole ExecutorService if one (specific thread) of the threads managed by it fails with an exception. Is it ok to simply call ExecutorService#shutdown from within the thread?

With Executorservice , if getting returned data from a thread ( using .get() method ) fails with an Exception , an ExecutionException will be thrown .
You have 2 case : passing Runnable to the submit method , or passing a Callable , in both of those cases you can use .get() method to retrieve data from the thread after execution.
So you can add .get() method to all the execution of threads and surround the calls of the submit method with a try catch block that handle ExecutionException .
This example will explain the idea :
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
static ExecutorService service = Executors.newFixedThreadPool(3);
public static void main(String[] args) {
try {
// Callable
System.out.println(service.submit(() -> {
return "Hello";
}).get());
} catch (ExecutionException e) {
System.out.println(e.getMessage());
// shutDown the service : if you delete the next line , service will still
// working
service.shutdownNow();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
// Runnable
service.submit(() -> {
throw new IOException();
}).get();
} catch (ExecutionException e) {
System.out.println(e.getMessage());
// shutDown the service : if you delete the next line , service will still
// working
service.shutdownNow();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Related

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.

The execution of the program doesn't end though the program executed successfully when using threads

I am exploring java.util.concurrent.*
Calculating the square and waiting using Thread.sleep(5000) , the program works as expected, but never terminates.
The red square in eclipse is "ON", that we usually use to terminate the program.
Can you please help in understanding why the program doesn't terminate on completion??
public static void main(String[] args) throws InterruptedException, ExecutionException {
// TODO Auto-generated method stub
try {
SquareCalculator sqC = new SquareCalculator();
sqC.display(1);
Future<Integer> result = sqC.calculate(5);
while(!result.isDone())
{
System.out.println("Waiting for the calculation");
Thread.sleep(1000);
//result.cancel(true);
}
Integer square = result.get();
System.out.println(square);
}catch(Exception e)
{
e.printStackTrace();
System.out.println("Calclulation was interrupted");
}
}
public class SquareCalculator {
private ExecutorService ex = Executors.newSingleThreadExecutor();
public void display(int i) {
// TODO Auto-generated method stub
System.out.println(i);
}
public Future<Integer> calculate(Integer inp)
{
try {
System.out.println("Before sending request");
Future<Integer> res = ex.submit(()->{
Thread.sleep(5000);
return inp*inp;
});
System.out.println("Request sent to caluclate and waiting for the result");
return res;
}catch(Exception e)
{
System.out.println("calculation was interrupted");
return null;
}
//return ex.submit(()->squareing(inp));
}
}
OUTPUT
1
Before sending request
Request sent to caluclate and waiting for the result
Waiting for the calculation
Waiting for the calculation
Waiting for the calculation
Waiting for the calculation
Waiting for the calculation
25
You need to refactor your code and return the object instead of Future. You should also shutdown executor when you are done.
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SquareCalculator {
private ExecutorService ex = Executors.newSingleThreadExecutor();
public void display(int i) {
// TODO Auto-generated method stub
System.out.println(i);
}
public Integer calculate(Integer inp) {
Integer result;
try {
System.out.println("Before sending request");
Future<Integer> res = ex.submit(() -> {
Thread.sleep(5000);
return inp * inp;
});
System.out.println("Request sent to caluclate and waiting for the result");
result = res.get();
ex.shutdown();
return result;
} catch (Exception e) {
System.out.println("calculation was interrupted");
return null;
}
//return ex.submit(()->squareing(inp));
}
public static void main(String[] args) throws InterruptedException,
ExecutionException {
// TODO Auto-generated method stub
try {
SquareCalculator sqC = new SquareCalculator();
sqC.display(1);
Integer result = sqC.calculate(5);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Calclulation was interrupted");
}
}
}
I would rather create an executor outside the Calculator class and the pass it in the constructor.
This way the application has control over the ExecutorService and shut it down when necessary.
Also, if you create more then one instance of a calculator, all instance use the same executor service, so you can control how many instance can run in parallel.
Blocking in the calculate method works, but defeats the purpose of using another thread to make an async calculation.
public static void main(String[] args) {
// The executor is created by the application and then
// passed to the calculator
ExecutorService executor = Executors.newCachedThreadPool();
SquareCalculator calculator = new SquareCalculator(executor);
// calculate does not block
Future<Integer> calculate = calculator.calculate(12);
try {
while(true) {
try {
// wait a limited amount of time for the computation to complete
Integer result = calculate.get(1, TimeUnit.SECONDS);
System.out.println(result);
if(calculate.isDone()) {
// If the computation was either complete or cancelled just quit
break;
}
} catch (TimeoutException e) {
// We expect timeouts so we don't quit the loop for them
System.out.println("Waiting for result");
}
}
} catch (InterruptedException | ExecutionException e) {
// If there was an error or the computation was interrupted just quit.
e.printStackTrace();
}
// Shut down the executor so we do not leak pools.
executor.shutdown();
}
public class SquareCalculator {
private ExecutorService ex;
public SquareCalculator(ExecutorService ex) {
super();
this.ex = ex;
}
public void display(int i) {
System.out.println(i);
}
public Future<Integer> calculate(Integer inp) {
try {
System.out.println("Before sending request");
Future<Integer> res = ex.submit(() -> {
Thread.sleep(5000);
return inp * inp;
});
System.out.println("Request sent to caluclate and waiting for the result");
return res;
} catch (Exception e) {
System.out.println("calculation was interrupted");
return null;
}
}
}
If you want the VM to shut down, call System.exit(). Yes, the VM can automatically close without calling that method as well; it does this if ALL still 'live' threads have the 'daemon' flag up (the Thread class has a .setDaemon method for this purpose), but that's bad code style. If the point is to shut down, then shut down (with System.exit).
Specifically here, the threads created by Executors.newSingleThreadExecutor(); aren't marked as daemon threads. You can fix that by supplying a thread creator to the call.
But, really, don't. Use System.exit.

How to start and stop Stream using AsyncHttpClient

I have implemented a Steaming API for twitter. I get the streams perfectly. However, My program never ends. I have tried many combinations but can't figure out why. I am suing Apache AsyncHttpClient in java. My goal is to start the stream for example for 10 seconds, get the streams, and gracefully close the stream and exit the application (I am expecting this to happen when my Main method ends naturally). This is the code below:
public static void main(String[] args) throws Exception
{
TwitterStreamingHttpClient client = new TwitterStreamingHttpClient();
Executor ex = Executors.newSingleThreadExecutor();
ex.execute(client);
Thread.sleep(5000);
client.ceaseStream();
LOG.debug("Keeps running");
}
and this:
public class TwitterStreamingHttpClient extends DefaultHttpAsyncClient implements Runnable
{
private final static Logger LOG = LoggerFactory.getLogger(TwitterStreamingHttpClient.class);
/**
* #throws IOReactorException
*/
public TwitterStreamingHttpClient() throws IOReactorException
{
super();
// TODO: parametrize it, load from config file, spring config file?
this.getCredentialsProvider().setCredentials(new AuthScope("stream.twitter.com", 80),
new UsernamePasswordCredentials("username", "password"));
this.start();
}
public void initiateStream() throws UnsupportedEncodingException, InterruptedException, ExecutionException
{
String requestContent = new String();
requestContent = "track=NothingFeelsBetterThan";
Future future = this.execute(HttpAsyncMethods.createPost(
"https://stream.twitter.com/1.1/statuses/filter.json", requestContent,
ContentType.APPLICATION_FORM_URLENCODED), new TwitConsumer(), null);
Boolean result = future.get();
if(result==null)
{
LOG.error("Requested to close stream!");
return;
}
}
public void ceaseStream()
{
try
{
this.shutdown();
LOG.info("Shutting down the stream");
}
catch (InterruptedException e)
{
LOG.debug("InterruptedException {}", e);
}
}
/*
* (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run()
{
Thread.currentThread().setName("initiateSTream Thread");
try
{
initiateStream();
Thread.currentThread().interrupt();
}
catch (UnsupportedEncodingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ExecutionException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I tried to add a return whereever I though it mightbe helpful. but no luck. Can someone help me with this?
Edit 1: When I use the debug mode, I can see that the "initiateSTream Thread" thread. is still running while the main thread is gone!
Edit 2 (Solution): In the main method, I replaced:
Executor ex = Executors.newSingleThreadExecutor();
ex.execute(client);
with:
Thread thread = new Thread(client);
thread.start();
Now my programs ends after the designated time of streaming. But why? What is the difference between the two approaches?!

How to Catch Timed Out Exception

Code :
Class Manager {
Future fu = pool.invokeAll(workers, SEARCH_TIMEOUT, TimeUnit.SECONDS);
// calling the invoke call
search search= fu.get();
// callable
}
public class Search implements Callable<Search> {
Search call() {
// multiple workers will execute Code So don't want to catch timed out exception in here
// api value will be changing based on corresponding reference
api.search_api();
}
}
class api()
{
search_api(){
// How to catch a timed out exception in here
// catch(TimedoutException){} did not work in here
}
}
Is there a way that I can catch the TimedOut exception in the Class api under method search_api()?
You can catch TimeoutException like this code :
try {
Future fu = pool.invokeAll(workers, SEARCH_TIMEOUT,
TimeUnit.SECONDS);
// calling the invoke call
search search = fu.get();
} catch (TimeoutException e) {
e.printStackTrace();
}
You can also do it by the following way
try{
.
.
.
.
catch (RuntimeException e) {
// TODO: handle exception
}

How to Stop long duration execution task ( e.g. Infinite Loop) execution inside a Executor Service

Below is a sample program. If i uncomment the Thread.sleep it works fine.
But there may be some need, where we are not sure how much time the code written inside Call method takes, can be a infinite time. Or, can be a bad program where the DB connection logic inside Call method takes more time and we need to kill.
Could you please tell, why the below code does not work if i comment the thread.sleep and how to kill and stop that without writing Thread.interrupted condition. (Assume i do not have permission write any logic inside the Call method)
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class stopThreadTest {
public static void main(String[] args) {
java.util.concurrent.ExecutorService executor = null;
Future a1 = null;
try {
executor = java.util.concurrent.Executors.newFixedThreadPool(4);
a1 = executor.submit(new java.util.concurrent.Callable() {
public String call() throws Exception {
int i = 0;
while (true) {
//Thread.sleep(100);
// System.out.println("hello");
if (i > 10)
break;
}
return null;
}
});
// Wait until all threads are finish
/*
* while (!executor.isTerminated()) { }
*/
System.out.println("Calling PartialOrFullSuccessCheck");
try {
boolean isThreadError = (a1 != null) ? ((a1.get(2,
TimeUnit.SECONDS) == null) ? false : true) : false;
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// interrupts the worker thread if necessary
System.out
.println("Cancelled" + a1.isDone() + a1.isCancelled());
a1.cancel(true);
System.out.println("encountered problem while doing some work");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// interrupts the worker thread if necessary
System.out
.println("Cancelled" + a1.isDone() + a1.isCancelled());
a1.cancel(true);
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// interrupts the worker thread if necessary
System.out
.println("Cancelled" + a1.isDone() + a1.isCancelled());
a1.cancel(true);
}
} finally {
System.out.println("ShutDown Executor");
executor.shutdown();
}
}
}
There is no safe way to stop a thread without its cooperation. Threads allow other threads to stop them by being interrupted, by periodically checking the value of some shared variable or both. Other than that, the only safe thing to do is shut down the JVM (the whole process). This post is quite detailed:
How do you kill a thread in Java?

Categories

Resources