How ExecutorService works when submit a callable task with callback - java

How to add custom check in executorService.submit() callback.
I want my thread not to do anything, whenever flag is true. If flag is false then it should work as usual.
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class test{
private static volatile boolean flag= false;
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Boolean> callableTask = () -> {
return isFlag();
};
Future a = submitAsync(callableTask);
System.out.println("tartest"+a.get());
}
public static Future submitAsync(Callable taskToRun) {
ExecutorService e1 = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder().namingPattern("").build());
return e1.submit(() -> {
try {
if (flag) {
return;
}
taskToRun.call();
} catch (Exception e) {
System.out.println("garbage ---");
}
});
// return e1.submit(taskToRun);
}
public static boolean isFlag() {
return true;
}
}
Here, a.get() is returning null. If I replace e1.submit(....) with e1.submit(taskToRun), which is commented in given code snippet then its working fine. So why a.get() is null?

return e1.submit(() -> {
try {
if (flag) {
return;
}
taskToRun.call();
} catch (Exception e) {
System.out.println("garbage ---");
}
});
In this snippet, the lambda passed to submit method on ExecutorService e1 is interpreted as a Runnable and that is why the return value is null. Check this documentation for more details. You need to pass the callable taskToRun itself to e1.submit() to be able to get the return value of the callable. Also, it would be cleaner to put the logic inside the Callable itself.
I have rewritten the sample code to achieve your requirement.
package stackoverflow.test;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class test{
private static volatile boolean flag = true;
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Boolean> callableTask = () -> {
if (flag) {
System.out.println("Flag is true, returning without executing callable logic !");
return false;
}
System.out.println("Flag is false, executing callable logic !");
return isFlag();
};
Future a = submitAsync(callableTask);
System.out.println("test " + a.get());
}
private static Future<Boolean> submitAsync(Callable<Boolean> taskToRun) {
ExecutorService e1 = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder().namingPattern("").build());
return e1.submit(taskToRun);
}
private static boolean isFlag() {
return true;
}
}

Your submitAsync method returns a Future that is the result of calling ExecutorService.submit(Runnable). From the documentation of that method:
Submits a Runnable task for execution and returns a Future representing that task. The Future's get method will return null upon successful completion.
If you want to return a Future that yields a value, add return statements to your lambda, so it will be interpreted as a Callable instead of a Runnable:
return taskToRun.call();
} catch (Exception e) {
e.printStackTrace();
return null;
}

Related

Java concurrent programming - endless loop

I am reading the book Introducing Play Framework: Java Web Application Development (ISBN 978-1-4842-5645-9) and there is this example on Callable:
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 CallableClient {
/**
* #param args
*/
// Step1 : Create a Runnable
public static void main(String[] args) {
Callable callableTask = new CallableTask();
// Step 2: Configure Executor
// Uses FixedThreadPool executor
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(callableTask);
boolean listen = true;
while (listen) {
if (future.isDone()) {
String result;
try {
result = future.get();
listen = false;
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
executor.shutdown();
}
}
My question is, if the computation of the Future throws and exception, will the while loop run forever?
In my opinion, yes, it will loop forever.
First, if the Future computation throws an exception, then
future.isDone()
always evaluates to true. So we reach the inside of the if, where the stopping condition can be set. Still Ok.
Second, as per future documentation, when reaching line
result = future.get();
it will always throw ExecutionException because the computation threw an exception. This exception is caught in the try-catch block, without reaching the stopping condition precondition, which is
listen = false
Lastly, the above will create an endless cycle.
Is there any mistake in my assumptions or is the author of the example really wrong?
The program mentioned above cycles forever, if the callable throws an exception.
This is a code snippet with the callable that throws an exceptions. Executing compiled snippet loops forever.
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 CallableClient {
public static class CallableTask implements Callable<String> {
#Override
public String call() throws Exception {
throw new Exception();
}
}
public static void main(String[] args) {
Callable<String> callableTask = new CallableTask();
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(callableTask);
boolean listen = true;
while (listen) {
if (future.isDone()) {
String result;
try {
result = future.get();
listen = false;
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
executor.shutdown();
}
}

Java lock's condition implementation

Need help with code at below link as it should run indefinitely likewise with any typical producer/consumer problem but somehow it is getting stuck on call of condition.signal(). What am I doing wrong here?
In main method, I have created two thread, one is consumer and other one is producer. it has shared task queue where both updates the entry.
package com.anurgup.handson;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionService implements Runnable {
Lock lock = new ReentrantLock();
Condition added = lock.newCondition();
Condition removed = lock.newCondition();
// type of service
String type;
// shared task for insertion and deletion of task
static Queue<Integer> task = new PriorityQueue<Integer>();
// max number of task allowed
private static final int MAX_SIZE = 5;
public ConditionService(String type) {
this.type = type;
}
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
service.submit(new ConditionService("producer"));
service.submit(new ConditionService("consumer"));
}
public void produce() {
try {
while (true) {
System.out.println("in producer...");
synchronized (task) {
while (task.size() == MAX_SIZE)
removed.await();
System.out.println("added item: " + task.size());
task.add(task.size());
added.signal();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void consume() {
try {
while (true) {
System.out.println("in consumer...");
synchronized (task) {
while (task.isEmpty())
added.await();
System.out.println("removed item: " + task.peek());
task.remove();
removed.signal();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
if (this.type.equals("producer"))
this.produce();
else
this.consume();
}
}
You're making two mistakes. First, your lock and conditions need to be static, or each task will only synchronize and wait on itself. Second, you need to use lock.lock(), not synchronized. It should look like this:
lock.lock();
try {
// wait
// produce/consume
} finally {
lock.unlock();
}

why this is not working - Unit testing a synchronous method using parameterized data of Junit?

I am trying to learn the JUnit and wanted to extend it to test in a multi-threaded way.
The class I want to test is PrimeNumberValidator. This just tests if a passed in number is prime or not.
package com;
public class PrimeNumberValidator {
public Boolean validate(final Integer primeNumber) {
System.out.println("Validating .............:" + primeNumber);
for (int i = 2; i < (primeNumber / 2); i++) {
if (primeNumber % i == 0) {
return false;
}
}
return true;
}
}
The PrimeNumberValidatorTest is the test class. The 2 of the test data are wrong and I have done this purposely to test for failure.
The test method testPrimeNumberValidator runs perfectly fine. But, the multi-threaded version testMultiThreadedPrimeNumberValidator always says 'pass' for even wrong data.
Why is this happening like this? How do solve this ?
package com;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
#RunWith(Parameterized.class)
public class PrimeNumberValidatorTest {
private Integer primeNumber;
private Boolean expectedValidation;
private PrimeNumberValidator primeNumberValidator;
#Before
public void initialize() {
primeNumberValidator = new PrimeNumberValidator();
}
// Each parameter should be placed as an argument here
// Every time runner triggers, it will pass the arguments from parameters we defined
public PrimeNumberValidatorTest(Integer primeNumber, Boolean expectedValidation) {
this.primeNumber = primeNumber;
this.expectedValidation = expectedValidation;
}
#Parameterized.Parameters
public static Collection primeNumbers() {
return Arrays.asList(new Object[][] {
{ 2, Boolean.FALSE},// 2 is prime so Test should fail
{ 6, Boolean.FALSE}, //is NOT prime so test should pass
{ 19, Boolean.TRUE},//is prime so test should pass
{ 22, Boolean.TRUE} //is NOT prime so test should fail
});
}
// This test will run 4 times since we have 4 parameters defined
#Test
public void testPrimeNumberValidator() {
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}
#Test
public void testMultiThreadedPrimeNumberValidator() {
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(new Runnable() {
public void run() {
for (int i = 0; i < 100; i++) {
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}
}
});
}
}
Referring to http://www.youtube.com/watch?v=wDN_EYUvUq0 as mentioned in one of the posts Weird problem using JUnit in multi-thread environment, tried as below. The exceptions are thrown, but the JUnit does not report failure :(
package com;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
#RunWith(Parameterized.class)
public class PrimeNumberValidatorTest {
volatile Exception exception;
volatile Error error;
private Integer primeNumber;
private Boolean expectedValidation;
private PrimeNumberValidator primeNumberValidator;
#Before
public void initialize() {
primeNumberValidator = new PrimeNumberValidator();
}
// Each parameter should be placed as an argument here
// Every time runner triggers, it will pass the arguments from parameters we defined
public PrimeNumberValidatorTest(Integer primeNumber, Boolean expectedValidation) {
this.primeNumber = primeNumber;
this.expectedValidation = expectedValidation;
}
#Parameterized.Parameters
public static Collection primeNumbers() {
return Arrays.asList(new Object[][] {
{ 2, Boolean.FALSE},// 2 is prime so Test should fail
{ 6, Boolean.FALSE}, //is NOT prime so test should pass
{ 19, Boolean.TRUE},//is prime so test should pass
{ 22, Boolean.TRUE} //is NOT prime so test should fail
});
}
// This test will run 4 times since we have 4 parameters defined
#Test
#Ignore
public void testPrimeNumberValidator() {
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}
#Test
public void testMultiThreadedPrimeNumberValidator() {
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(new Runnable() {
public void run() {
for (int i = 0; i < 1; i++) {
try{
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}catch(Error e){
System.out.println("error thrown :" + e);
error =e;
}catch(Exception e){
exception=e;
System.out.println("exception thrown :" + e);
}
}
}
});
}
#After
public void runAfterEveryTest() throws Exception{
if(null != error){
System.out.println("runAfterEveryTest throwing error...............");
throw error;
}
if(null != exception){
System.out.println("runAfterEveryTest throwing exception...............");
throw exception;
}
}
}
The reason the multi-threaded is always passing is the following:
first, the test method does nothing to wait for the multiple threads to complete therefore the #Test method is exiting before any errors are reported
second, the way that testing works is that the assert method throws an exception. The JUnit framework catches this exception by wrapping the #Test method and fails the test if an unexpected exception is thrown. However, in the multi-threaded test no exception is thrown from the #Test method because they are thrown within the threads and the test method does nothing to check this. One solution for this part would be to use an ErrorCollector
It got resolved with the below code. The addtion of Future related code made it work.
#Test
public void testMultiThreadedPrimeNumberValidator() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(100);
Future future = executor.submit(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try{
assertEquals(expectedValidation, primeNumberValidator.validate(primeNumber));
}catch(Error e){
System.out.println("error thrown :" + e);
//error =e;
System.out.println("error set to :" + e);
}catch(Exception e){
System.out.println("exception thrown :" + e);
//exception=e;
System.out.println("Exception set to :" + e);
}
}
}
});
future.get();
}

Working of Await and signal in concurrent Java

I am a beginner and I have to write a code for particular prob stmt. I wanna use locks to implement it. Beforehand, I gotto know the working of locks and its methods.
In my below code, I need the first thread to await and second thread to signal the first thread and wake up. But the signal is not waking up my waiting thread. Could anyone pls help.
package com.java.ThreadDemo;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadEx {
public static void main (String args[]) throws InterruptedException
{
ThreadMy mt[]=new ThreadMy[6];
int a=1, b=2;
mt[1] = new ThreadMy(a);
mt[2] = new ThreadMy(b);
mt[1].start ();
Thread.sleep(100);
mt[2].start ();
}
}
class ThreadMy extends Thread
{
final ReentrantLock rl = new ReentrantLock() ;
Condition rCond = rl.newCondition();
//private final Condition wCond = rl.newCondition();
int i;
int c;
public ThreadMy(int a)
{
c=a;
}
public void run()
{
System.out.print("\nThread "+c+" "+rl.isHeldByCurrentThread()+" "+rl.isLocked() );
rl.lock();
try
{
//for (i=0;i<2;i++)
System.out.print("\nThread "+c+" "+rl.isHeldByCurrentThread()+" "+rl.getHoldCount() );
try
{
if (c==1)
{
System.out.print("await\n");
rCond.await();
//rCond.await(200, TimeUnit.MILLISECONDS);
System.out.print("signal\n");
}
else
{
System.out.print("P");
rCond.signal();
Thread.sleep(2000);
System.out.print("P1");
}
//rCond.signal();
}
catch ( InterruptedException e)
{
//System.out.print("Exception ");
}
}
finally
{
rl.unlock();
}
System.out.print("\n run " + c);
}
}
You are not sharing lock and condition between threads. Each instance of ThreadMy is running with its own lock and condition object.

How can a Thread return a value after finishing its job?

Let's say we have this simple example:
public Example extends Thread{
String temp;
public Example(){
}
#Override
public void run(){
.
.
.
.
temp = "a_value";
}
public static void main(String[] args) {
Example th = new Example();
th.start();
}
}
How can the Thread after finishing its job return me the String temp?
Make use of the (relatively) new Callable<T> instead of Runnable (available in 1.5 and newer versions):
Here is a (simple) example:
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 Main {
public static void main(final String[] argv) {
final ExecutorService service;
final Future<String> task;
service = Executors.newFixedThreadPool(1);
task = service.submit(new Foo());
try {
final String str;
// waits the 10 seconds for the Callable.call to finish.
str = task.get(); // this raises ExecutionException if thread dies
System.out.println(str);
} catch(final InterruptedException ex) {
ex.printStackTrace();
} catch(final ExecutionException ex) {
ex.printStackTrace();
}
service.shutdownNow();
}
}
class Foo implements Callable<String> {
public String call() {
try {
// sleep for 10 seconds
Thread.sleep(10 * 1000);
} catch(final InterruptedException ex) {
ex.printStackTrace();
}
return ("Hello, World!");
}
}
Look at Future interface javadoc. It has sample usage showing you how to do this.
You can achieve this by the Observer pattern.
on finishing the thread notifies all listeners that it's finished and they can retrieve the value (through a getter). Or it can even already send the computed value.
Or you can use a task, see FutureTask, a runnable ( indeed as stated below a Callable ) that returns a result and can throw exceptions.
If you don't want to swap the solution to use Callable objects then you can use also queues and return the result from the threads that way.
I re-wrote your example like this:
import java.util.PriorityQueue;
import java.util.Queue;
public class GetResultFromThread {
public static void main(String[] args) throws Exception {
Queue<String> queue = new PriorityQueue<String>();
int expectedResults = 2;
for (int i = 0; i < expectedResults; i++) {
new Example(queue).start();
}
int receivedResults = 0;
while (receivedResults < expectedResults) {
if (!queue.isEmpty()) {
System.out.println(queue.poll());
receivedResults++;
}
Thread.sleep(1000);
}
}
}
class Example extends Thread {
private final Queue<String> results;
public Example(Queue<String> results) {
this.results = results;
}
#Override
public void run() {
results.add("result from thread");
}
}
Note that you shall think of synchronization and concurrency!

Categories