Java: ExecutorService and Callables, unable to catch exception - java

I'm trying to figure out why the below code doesn't print out the stack trace of a NumberFormatException when I run it?
I'm not sure if it is common to use callables and ExecutorService in this way, I googled and couldn't find a solution to my problem... there may be something really obvious that I'm not seeing.
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CallablesTest {
private final static ArrayList<Callable<Void>> mCallables = new ArrayList<>();
private final static ExecutorService mExecutor = Executors.newFixedThreadPool(4);
public static void main(String[] args) throws Exception{
testMethod();
}
static void testMethod() throws Exception {
mCallables.clear();
for(int i=0; i<4; i++){
mCallables.add(new Callable<Void>() {
#Override
public Void call() throws Exception {
//if (Thread.currentThread().isInterrupted()) {
// throw new InterruptedException("Interruption");
//}
System.out.println("New call");
Double.parseDouble("a");
return null;
} //end call method
}); //end callable anonymous class
}
try {
mExecutor.invokeAll(mCallables);
mExecutor.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}

I think I may have found the answer to my own question... if you get the future objects returned from ExecutorService.invokeAll... and then surround the Future "get" calls with a try/catch block, you can catch the exception
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadTest {
private final static ArrayList<Callable<Boolean>> mCallables = new ArrayList<>();
private final static ExecutorService mExecutor = Executors.newFixedThreadPool(4);
public static void main(String[] args) throws Exception{
testMethod();
}
static void testMethod() throws Exception {
mCallables.clear();
for(int i=0; i<4; i++){
mCallables.add(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
//if (Thread.currentThread().isInterrupted()) {
// throw new InterruptedException("Interruption");
//}
System.out.println("New call");
double d = Double.parseDouble("a");
return true;
} //end call method
}); //end callable anonymous class
}
try {
List<Future<Boolean>> f= mExecutor.invokeAll(mCallables);
f.get(1).get();
f.get(2).get();
f.get(3).get();
f.get(0).get();
} catch (Exception e) {
String s = e.toString();
System.out.println(s);
}
mExecutor.shutdown();
}
}

Related

Unable to set a boolean flag from scheduled executor service

I need to run a piece of code periodically. This code checks a condition and sets a boolean flag.
In order to run it periodically, I am using scheduledExecutorService.scheduleAtFixedRate method.
The scheduler works fine, but it is unable to set the flag.
The flag value is always false.
Please advise.
package healthCheck;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
private static ScheduledExecutorService scheduler;
public static void main(String[] args)
throws InterruptedException, ExecutionException {
scheduler = Executors.newSingleThreadScheduledExecutor();
Future<?> scheduledFuture = scheduler.scheduleAtFixedRate(
new SomeFiveSecondelyJob(), 1, 5, TimeUnit.SECONDS);
System.out.println("Flag at scheduler"+scheduledFuture.get());
}
public static void contextDestroyed() {
scheduler.shutdownNow();
}
}
The Runnable code:
package healthCheck;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class SomeFiveSecondelyJob implements Runnable {
#Override
public void run() {
URL url;
try {
url = new URL("https://www.google.co.in/");
HttpsURLConnection connection =
(HttpsURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
int code = connection.getResponseCode();
if (code / 100 == 2) {
ItSystemFlag.setFlag(true);
System.out.println("System is up");
} else {
ItSystemFlag.setFlag(false);
System.out.println("System unavailable: " + code);
}
} catch (Exception e) {
ItSystemFlag.setFlag(false);
e.printStackTrace();
}
System.out.println(ItSystemFlag.getFlag());
}
}
I am using a static volatile variable as a flag:
package healthCheck;
public class ItSystemFlag {
private static volatile Boolean flag = false;
public static void setFlag(Boolean flag) {
ItSystemFlag.flag = flag;
System.out.println("seting the flag to :" + ItSystemFlag.flag);
}
public static Boolean getFlag() {
return ItSystemFlag.flag;
}
}
Second client class:
package healthCheck;
public class Test2 {
public static void main(String[] args) throws InterruptedException {
for(int i=0;i<20;i++) {
System.out.println("From client "+ItSystemFlag.getFlag());
Thread.sleep(6000);
}
}
}
These are two different java processes. The global variable is not shared between them. Try:
public class Test {
private static ScheduledExecutorService scheduler;
public static void main(String[] args)
throws InterruptedException, ExecutionException {
scheduler = Executors.newSingleThreadScheduledExecutor();
Future<?> scheduledFuture = scheduler.scheduleAtFixedRate(
new SomeFiveSecondelyJob(), 1, 5, TimeUnit.SECONDS);
System.out.println("Flag at scheduler"+scheduledFuture.get());
for(int i=0;i<20;i++) {
System.out.println("From client "+ItSystemFlag.getFlag());
Thread.sleep(6000);
}
}
public static void contextDestroyed() {
scheduler.shutdownNow();
}
}
First run the scheduler and then in the same java process check the global flag.

Thread isn't resuming execution after notify()

I have two classes (Customer and Till). Customer thread waits until it is notified by a till thread. In my program, the customer thread is not executing it's code after being notified by the till thread. The till thread continues it's execution.
Customer.java (Customer thread extends Thread)
import java.util.concurrent.*;
import java.util.*;
public class Customer extends Thread
{
Random random_generator = new Random();
public int minimumQueueLength;
public Set set;
public Iterator iterator;
public boolean placed_in_queue;
public List<Integer> queue_length_list;
public CopyOnWriteArrayList till_set = new CopyOnWriteArrayList();
public Till till, till_to_join;
public final Object lock;
public Customer(CopyOnWriteArrayList till_set)
{
this.till_set = till_set;
this.placed_in_queue = false;
queue_length_list = new ArrayList<Integer>();
lock = new Object();
}
public void run()
{
try
{
place_in_queue();
}
catch (InterruptedException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(placed_in_queue)
{
synchronized(this.lock)
{
System.out.println(this.getName()+" waiting");
try {
this.lock.wait();
System.out.println(this.getName()+" has been woken");
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
else
{
}
}
public void place_in_queue() throws InterruptedException
{
placed_in_queue = false;
iterator = till_set.iterator();
while(iterator.hasNext())
{
till = (Till)iterator.next();
queue_length_list.add(till.customer_queue.size());
}
minimumQueueLength =
queue_length_list.indexOf(Collections.min(queue_length_list));
if(minimumQueueLength < 5)
{
try
{
till_to_join = (Till)till_set.get(minimumQueueLength);
till_to_join.customer_queue.put(this);
placed_in_queue = true;
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Till.java (till thread extends Thread)
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.*;
public class Till extends Thread
{
BlockingQueue<String> item_queue = new ArrayBlockingQueue<String>(200);
BlockingQueue<Customer> customer_queue = new ArrayBlockingQueue<Customer>(10);
public Random random;
public Customer c;
public Till(BlockingQueue<String> item_queue) throws InterruptedException
{
this.item_queue = item_queue;
random = new Random();
}
public void run()
{
while(true)
{
try
{
c = customer_queue.take();
synchronized(c.lock)
{
System.out.println(this.getName()+" Waking up : "+c.getName());
c.lock.notify();
System.out.println(c.getName()+" has been notified!");
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
CustomerGenerator.java
import java.util.*;
import java.util.concurrent.*;
public class CustomerGenerator extends Thread
{
public int customer_generation_rate;
//0 - slow
//1 - fast
public Random random_generator;
public static BlockingQueue<String> item_queue = new ArrayBlockingQueue<String>(200);
public static CopyOnWriteArrayList till_set = new CopyOnWriteArrayList();
public int i;
public CustomerGenerator(int customer_generation_rate, CopyOnWriteArrayList till_set)
{
this.customer_generation_rate = customer_generation_rate;
this.till_set = till_set;
this.i = 0;
random_generator = new Random();
}
public void run()
{
while(i<1)
{
switch(customer_generation_rate)
{
case 0 : try
{
Thread.sleep(random_generator.nextInt(1000));
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case 1 : try
{
Thread.sleep(random_generator.nextInt(500));
}
catch(InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
default : customer_generation_rate = 0;
break;
}
Customer customer = new Customer(till_set);
customer.start();
total_customer_count++;
i++;
}
}
}
Driver.java
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Driver
{
public static BlockingQueue<String> item_queue = new ArrayBlockingQueue<>(200);
public static CopyOnWriteArrayList<Till> till_set = new CopyOnWriteArrayList<Till>();
public static Set set;
public static Iterator iterator;
public static int i;
public static final int till_count = 5;
public static Thread till_thread;
public static Till till_object;
public static ExecutorService till_service = Executors.newFixedThreadPool(5);
public static void main(final String[] args) throws InterruptedException
{
for(i=0; i<till_count; i++)
{
till_object = new Till(item_queue);
till_set.add(till_object);
}
final CustomerGenerator customer_generator = new CustomerGenerator(0, till_set);
customer_generator.start();
Thread.sleep(5000);
for(final Till t : till_set)
{
till_service.submit(t);
}
}
}
Output Obtained:
Thread-7 waiting
Thread-1 Waking up : Thread-7
Thread-7 has been notified!
Expected Output:
Thread-7 waiting
Thread-1 Waking up : Thread-7
Thread-7 has been notified!
Thread-7 has been woken
Please help. Thank you. :)
CustomerGenerator generates one customer only when invoked. Making a mcve version of it makes it very clear:
//i was initialized: i=0;
public void run()
{
while(i<1)
{
final Customer customer = new Customer(till_set);
customer.start();
i++;
}
}
I do not think that is what you meant.
I find mcve a very useful technique. Not only it makes helping much easier, it
is a powerful debugging tool. It many case, while preparing one, you are likely to find the problem. mcve should demonstrate the problem, and not your application.
There may be other issues in the code. For more help please post Mcve.
Some other comments:
In CustomerGenerator you pass a reference of all tills to a Customer by:
final Customer customer = new Customer(till_set); which is later used for selecting a till. I think till selection calculation would better be done in another class, say TillsManager which can have a stack of all customers waiting for a till.
In Driver defining
public static Till till_object;
for(i=0; i<5 ; i++)
{
till_object = new Till(item_queue);
till_set.add(till_object);
}
means you will end up with 5 times the same object in till_set. I assume you wanted :
for(i=0; i<till_count; i++)
{
Till till_object = new Till(item_queue);
till_set.add(till_object);
}
Just wait from the Till until it the Queue gets more than zero elements. From the customer thread after adding themself to the queue, notify the Till.

How can I manage multiple callable threads result without a specific order?

Basically something like this:
ExecutorService service = Executors.newFixedThreadPool(2);
Future<Boolean> futureFoo = service.submit(myFooTask);
Future<Boolean> futureBar = service.submit(myBarTask);
int resultFoo;
boolean resultBar;
resultFoo = futureFoo.get();
resultBar = futureBar.get();
I want to do an event to manage independently the first result I get, without waiting for futureFoo to finish first.
you can use CompletionService. The results of the callables are put in a queue, and you can take the results of the tasks as soon as they complete. in this case, you don't need to wait for the results of Foo if Bar completes earlier. for example:
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class CompletionServiceExample {
private static Logger LOGGER = Logger.getLogger("CompletionServiceExample");
public static void main(String[] args) throws InterruptedException {
CompletionServiceExample completionServiceExample = new CompletionServiceExample();
completionServiceExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
final CompletionService<Boolean> completionService = new ExecutorCompletionService<>(executorService);
completionService.submit(new Foo());
completionService.submit(new Bar());
int total_tasks = 2;
for(int i = 0; i < total_tasks; ++i) {
try {
final Future<Boolean> value = completionService.take();
System.out.println("received value: " + value.get());
} catch (ExecutionException e) {
LOGGER.log(Level.WARNING, "Error while processing task. ", e);
} catch (InterruptedException e) {
LOGGER.log(Level.WARNING, "interrupted while waiting for result", e);
}
}
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.SECONDS);
}
}
class Foo implements Callable<Boolean> {
#Override
public Boolean call() throws Exception {
Thread.sleep(5000);
return true;
}
}
class Bar implements Callable<Boolean> {
#Override
public Boolean call() throws Exception {
Thread.sleep(1000);
return false;
}
}
If you want to return different types, you can use a base class and do downcasting. for example like this:
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class CompletionServiceExample {
private static Logger LOGGER = Logger.getLogger("CompletionServiceExample");
public static void main(String[] args) throws InterruptedException {
CompletionServiceExample completionServiceExample = new CompletionServiceExample();
completionServiceExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
final CompletionService<Base> completionService = new ExecutorCompletionService<>(executorService);
completionService.submit(new FooBase());
completionService.submit(new BarBase());
int total_tasks = 2;
for (int i = 0; i < total_tasks; ++i) {
try {
final Future<Base> value = completionService.take();
Base base = value.get();
if (base instanceof FooBase) {
int myInteger = ((FooBase) base).getValue();
System.out.println("received value: " + myInteger);
}
if (base instanceof BarBase) {
boolean myBoolean = ((BarBase) base).isValue();
System.out.println("received value: " + myBoolean);
}
} catch (ExecutionException e) {
LOGGER.log(Level.WARNING, "Error while processing task. ", e);
} catch (InterruptedException e) {
LOGGER.log(Level.WARNING, "interrupted while waiting for result", e);
}
}
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.SECONDS);
}
}
class Base {
}
class FooBase extends Base implements Callable<Base> {
private int value;
#Override
public Base call() throws Exception {
Thread.sleep(5000);
value = 10;
return this;
}
public int getValue() {
return value;
}
}
class BarBase extends Base implements Callable<Base> {
private boolean value;
#Override
public Base call() throws Exception {
Thread.sleep(1000);
value = false;
return this;
}
public boolean isValue() {
return value;
}
}

Exception handling in call method of Java executor framework

Wondering if there are customized exception happening in call method, wondering what is the best practice for the client to get the exception? Shall we catch exception when call the get method? Or before we call get method, exception will be thrown from call method (from thread pool)? Thanks.
I am referring to the sample below,
http://www.vogella.com/tutorials/JavaConcurrency/article.html
package de.vogella.concurrency.callables;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Long> {
#Override
public Long call() throws Exception {
long sum = 0;
for (long i = 0; i <= 100; i++) {
sum += i;
}
return sum;
}
}
package de.vogella.concurrency.callables;
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 class CallableFutures {
private static final int NTHREDS = 10;
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
List<Future<Long>> list = new ArrayList<Future<Long>>();
for (int i = 0; i < 20000; i++) {
Callable<Long> worker = new MyCallable();
Future<Long> submit = executor.submit(worker);
list.add(submit);
}
long sum = 0;
System.out.println(list.size());
// now retrieve the result
for (Future<Long> future : list) {
try {
sum += future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println(sum);
executor.shutdown();
}
}

Awaitility.await().atMost(...) causes program to exit if time out interval expires?

This question regards com.jayway.awaitility.Awaitility.
I just tried Awaitility.await() and it seems to have some odd behavior.
In the test method below if I comment out testWithFuture() and enable
testWithAwaitility(), I never see the message "end " printed out.
I see 'start ', then the program just exits, and the second
print statement never seems to be reached.
So as a work around I decided to use Settable{Future}.. If anyone else has the same issue then maybe the work-around I provide will be useful.. Even better would be to get a nice answer ;^) ! thanks in advance / chris
THE CODE:
import com.google.common.util.concurrent.SettableFuture;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static com.jayway.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.SECONDS;
public class AwaitTest {
static volatile boolean done = false;
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
testWithFuture();
//testWithAwaitility();
}
private static void testWithAwaitility() {
System.out.println("start " + new Date());
new Thread(new Runnable(){
public void run(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
done = true;
}
}).start();
await().atMost(2, SECONDS).until(new Callable() {
#Override
public Boolean call() throws Exception {
return done;
}
});
System.out.println("end " + new Date()); // NEVER Reached. i wonder why?
}
// This does what I want.
//
private static void testWithFuture() throws InterruptedException, ExecutionException, TimeoutException {
System.out.println("start testWithFuture");
final SettableFuture future = SettableFuture. create();
new Thread(new Runnable(){
public void run(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
future.set("Hello");
}
}).start();
String result = future.get(4, TimeUnit.SECONDS);
if (! result.equals("Hello")) {
throw new RuntimeException("not equal");
} else {
System.out.println("got Hello");
}
}
}
CORRECTED CODE ->
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static com.jayway.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.SECONDS;
public class Sample {
static volatile boolean done = false;
public static void main(String[] args) {
testWithAwaitility();
}
private static void testWithAwaitility() {
System.out.println("start " + new Date());
new Thread(new Runnable(){
public void run(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
done = true;
}
}).start();
try {
await().atMost(2, SECONDS).until(new Callable() {
#Override
public Boolean call() throws Exception {
return done;
}
});
} catch (Exception e) {
System.out.println("FAILED");
e.printStackTrace();
}
System.out.println("end " + new Date()); // REACHED this statement after correction
}
}
According to the documentation, await() throws a TimeoutException if the timeout is reached and the condition is not true, so your method ends at this point because the exception is propagated up through the stack. This explains the behavior. You should see a stacktrace, however.
If you want to continue executing code afterwards, it seems you would need to catch this exception.

Categories

Resources