The code below checks the usage of ExecutorCompletionService from Java Concurrency framework (the IDE being used is Netbeans).
But the program doesn't terminate. Why?
Code:
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
public class TestFuture {
public static void main(String... args) throws InterruptedException, ExecutionException {
Executor ex = Executors.newCachedThreadPool();
CompletionService<Long> cs = new ExecutorCompletionService<Long>(ex);
cs.submit(new Worker());
cs.submit(new Worker());
cs.submit(new Worker());
for (int i = 0; i < 3; i++) {
long l = cs.take().get();
//utilize the result
System.out.println(l);
}
}
}
class Worker implements Callable {
#Override
public Long call() throws Exception {
//do some task and return back
return System.currentTimeMillis();
}
}
Threads in thread pool will keep running when main is finished. That's why JVM won't shut down. You need to either use daemon-threads, or shutdown the pool explicitly.
Here's an example:
ExecutorService ex = Executors.newCachedThreadPool();
// do all your submission work here
ex.shutdown();
Related
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();
}
}
Listed below is example code that I found for using the java.util.concurrent.ExecutorService. The main class includes a shutdown() method that calls the shutdown() method on the ExecutorService. What I do not understand from this example is when this method would be invoked.
Thanks.
package multithreadingexample;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MultithreadingExample {
ExecutorService executor = Executors.newFixedThreadPool(3);
public void start() throws IOException {
int i=0;
while (!executor.isShutdown())
executor.submit(new MyThread(i++));
}
public void shutdown() throws InterruptedException {
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);
executor.shutdownNow();
}
public static void main(String argv[]) throws Exception {
new MultithreadingExample().start();
}
}
class MyThread implements Runnable {
private final int i;
MyThread(int i) {
this.i = i;
}
#Override
public void run() {
System.out.println("I am in thread:"+i);
}
}
Why it is there:
To provide a way to shut down the ExecutorService to stop it from running tasks and to free the threads that it is using.
How it gets called:
You need to call it when you are done using the ExecutorService. In the example code you provided it is not called anywhere.
From the documentation:
The shutdown() method will allow previously submitted tasks to execute
before terminating, while the shutdownNow() method prevents waiting
tasks from starting and attempts to stop currently executing tasks.
Below is a unit test which uses ScheduledExecutorService to execute a scheduled runnable every second :
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
public class ConcurrentRequestSimulator {
private static final int NUMBER_REQUESTS = 4;
#Test
public void testGetToDoList() {
try {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
scheduler.scheduleAtFixedRate(new RequestThreadInvoker(), 0, 1, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
private final class RequestThreadInvoker implements Runnable {
public void run() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 1; i <= NUMBER_REQUESTS; i++) {
es.execute(new RequestThread());
}
es.shutdown();
while (!es.isTerminated()) {
}
}
}
private final class RequestThread implements Runnable {
public void run() {
try {
System.out.println("in RequestThread");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The line System.out.println("in RequestThread"); in RequestThread does not appear to be invoked as no output is displayed to console.
I think the issue is that since the test runs to completion, it causes the scheduler to stop scheduling? Can the test be updated so that scheduler is not terminated and RequestThreadInvoker is invoked repeatedly once per second ?
In RequestThreadInvoker I create a new instance of ExecutorService. Could this be causing the issue ?
Adding Thread.sleep(99000); to end of test causes test to wait 99 seconds which is enough time for test to run.
I'm using a quad core PC (Intel CORE i7) but I execute the task on 4 threads it takes 14s instead of somthing aroud 6s which is the time taken by one thread to perform the task. Is it because of all the initialisatioin (creation of the 3 other threads, ...) ?
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;
import java.util.concurrent.TimeUnit;
import junit.framework.TestResult;
import junit.framework.TestSuite;
import com.google.common.base.Stopwatch;
public class MultithreadWithExecutor {
private static class ExecuteLongTask implements Callable<Integer>{
private static final int ARRAY_SIZE = 10000;
private static final int NB_TEST_ALL = 10000;
private static final int NB_TEST_QUART = NB_TEST_ALL/4;
#Override
public Integer call() throws Exception {
for (int i = 0; i < NB_TEST_QUART; i++) {
//Create a list
List<Double> lst = new ArrayList<Double>();
for (int j = 0; j < ARRAY_SIZE; j++) {
lst.add(Math.random());
}
//sort it
Collections.sort(lst);
}
return 0;
}
}
public static void main(String[] ar) throws InterruptedException, ExecutionException {
int n = 4;
// Build a fixed number of thread pool
ExecutorService pool = Executors.newFixedThreadPool(n);
Stopwatch watch = Stopwatch.createStarted();
Future<Integer> future1 = pool.submit(new ExecuteLongTask());
Future<Integer> future2 = pool.submit(new ExecuteLongTask());
Future<Integer> future3 = pool.submit(new ExecuteLongTask());
Future<Integer> future4 = pool.submit(new ExecuteLongTask());
// Wait until threads finish
int testRuns= future1.get();
testRuns+=future2.get();
testRuns+=future3.get();
testRuns+=future4.get();
long elapsed = watch.elapsed(TimeUnit.MILLISECONDS);
// took ~14s instead of ~6s (time taken by on thread to execute the task)
System.out.println("Runned: "+testRuns+" in: "+elapsed);
pool.shutdown();
}
}
Check the following things:
your test is not using synchronized on a shared object
you don't get an Exception when adding try { (new MyTestCase("test")).runBare(); } catch (Throwable throwable) { throwable.printStackTrace(); } to your call method. If you get
java.lang.IllegalAccessException: Class junit.framework.TestCase can not access a member of class ...MyTestCase with modifiers "public" make the class and the classes including that class public
if you get junit.framework.AssertionFailedError: Method "test" not found change either the parameter to new MyTestCase("test") to reflect the name of your function or change the name of your function to test
If your problem can not be solved this way please show us a MyTestCase-class which exhibits the behaviour.
The output of the following simple code is a little odd to me.
it miss out some of the numbers between 0 and 100 to print on the console.
could anyone explain why it omit to print? i am completely new to concurrency programming.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
public class SimpleTest {
#Test
public void testSimple() throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i = 0; i <= 100; i++) {
executorService.execute(new SimpleRunnable(i));
}
executorService.shutdown();
}
}
class SimpleRunnable implements Runnable {
int i;
public SimpleRunnable(int i) {
this.i = i;
}
public void run() {
synchronized(System.out) {
System.out.println(i);
}
}
}
You should wait for the executor service to finish after calling shutdown
executorService.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS); // Wait for the tasks to finish.
// and flush!
System.out.flush();
I suspect the threads created are daemon threads, which do not prevent a JVM shutdown. Since the threads are kicked off and forgotten, after your call to shutdown, the method returns and then the JVM exits because there is nothing else to do. Unfinished work never gets done.
As Elliot pointed out, use the awaitTermination method:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long, java.util.concurrent.TimeUnit)