Exception handling in call method of Java executor framework - java

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();
}
}

Related

Java - Implementing a thread-safety set method with returning the new value

I am trying to implement a set method for an AtomicInteger and return the new value. Unfortunately, it comes to race conditions. I think it is because the two statements this.counter.set(newValue); and return this.counter.get(); are not Atomic if I let them run together. I also tried to use a synchronized block, but it did not help either. Do you know how I can set a new Value and return the value in an atomic method? For reasons, I can't change the method signature.
Here is the Class where the set method should be:
import java.util.concurrent.atomic.AtomicInteger;
import util.Incrementer;
public class AtomicIncrementer implements Incrementer {
private AtomicInteger counter = new AtomicInteger();
private int startValue;
public AtomicIncrementer(int startValue) {
this.startValue = startValue;
this.counter.set(startValue);
}
#Override
public int setValue(int newValue) {
// TODO: implement, do not change method the signature!
synchronized (this.counter) {
this.counter.set(newValue);
return this.counter.get();
}
}
}
I am running this test:
package incrementer;
import impl.AtomicIncrementer;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestAtomicIncrementer {
private final int defaultThreadPoolSize = 8;
private final int defaultThreadCount = 24;
#Test
void testSetValue() {
int newValue = (int) (Math.random() * 100);
AtomicIncrementer inc = new AtomicIncrementer(0);
ExecutorService executor = Executors.newFixedThreadPool(defaultThreadPoolSize);
for(int i = 0; i < defaultThreadCount; i++) {
executor.submit(() -> {
for(int j = 0; j < 1000; j++) {
inc.increment();
}
return null;
});
}
try {
assertEquals(newValue, executor.submit(() -> inc.setValue(newValue)).get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
try {
executor.shutdown();
assertTrue(executor.awaitTermination(60, TimeUnit.SECONDS));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
inc.setValue(newValue);
assertEquals(newValue, inc.getValue());
}
private List<Future<Integer>> executeOperation(Callable<Integer> op, AtomicIncrementer inc, int threadCount, int threadPoolSize) {
ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
List<Callable<Integer>> ops = new ArrayList<>(threadCount);
for(int i = 0; i < threadCount; i++) {
ops.add(op);
}
try {
return executor.invokeAll(ops);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Sometimes the test success and sometimes not, which seems like a race condition Problem for me.
What do you think?

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;
}
}

Java: ExecutorService and Callables, unable to catch exception

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();
}
}

Stop an infinite loop in an ExecutorService task

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
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;
class Task implements Callable<String> {
public String call() throws Exception {
String s = "initial";
try {
System.out.println("Started..");
/*for (int i=0;i<10000;i++) {
if (i % 2 == 0) {
System.out.println("Even");
}
}*/
boolean flag = true;
while(flag) {
}
System.out.println("Finished!");
s = "Done";
}
catch (RuntimeException e) {
s = "RuntimeException";
}
catch (Exception e) {
s = "Exception";
}
finally {
}
return s;
}
}
public class ExecutorServiceTest {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
List<Future<String>> result = executor.invokeAll(Arrays.asList(new Task()), 5, TimeUnit.SECONDS);
executor.shutdown();
Iterator<Future<String>> iter = result.iterator();
while (iter.hasNext()) {
System.out.println("Came here");
Future<String> fut = iter.next();
System.out.println(fut.get());
}
}
}
Is there a way in which i can stop the thread executing the infinite loop?
Yes, you can replace flag (or logically &&) with !Thread.currentThread().isInterrupted().
This way, when the task is canceled, the loop will be terminated.
The loop would look something like this:
while(!Thread.currentThread().isInterrupted() && flag) {
/* Do work. */
}
Use should be something like this:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> task = executor.submit(new Task());
String str;
try {
str = task.get(5, TimeUnit.SECONDS);
} finally {
task.cancel(true);
}
Think about using synchronized (this) { this.wait() } instead of sleep inside call(), and then when you set the boolean flag externally (perhaps directly or via a flag() method; with direct access make sure your flag variable is volatile) call task.notifyAll() to wake up the sleeping thread (make sure your task object is a local variable instead of having it anonymous so that you can call methods on it, and make flag a class attribute within Task).
It'll also be more efficient like that because loops waste cycles needlessly -- the exact mechanism is called a 'guarded block' (http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html). When you wake up out of the wait, test for the flag variable just to make sure it was set.
Edit: looked at the original question more closely and created an example using the existing code and principles (there's more than one way to skin a cat :)). Try this -- the loop here exits due to the interrupted status of the current thread, which has been canceled due to timeout:
package ett;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
class Task implements Callable<String> {
public String call() throws Exception {
String s = "initial";
System.out.println("Started..");
for (int i=0;;i++) {
if (i % 2 == 0) {
System.out.println("Even");
}
Thread.yield();
if (Thread.interrupted()) break;
}
System.out.println("Finished!");
s = "Done";
return s;
}
}
public class ExecutorServiceTest {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
List<Future<String>> result = executor.invokeAll(Arrays.asList(new Task()), 1, TimeUnit.SECONDS);
executor.shutdown();
System.out.println("came here");
for (Future<String> f : result) {
try {
System.out.println(f.get());
} catch (CancellationException e) {
e.printStackTrace();
}
}
}
}

Categories

Resources