Executor Future and Callable
Runnable
- no object can be returned
- no exception can be raised
Why thread pools?
- avoid performance overhead associated with starting a new thread
- each thread is allocated some memory for its stack
Executor
- task is executed in order of added, and not possible to know if given task is done or not
- if the task is not started yet, can cancel from the queue
- ExecutorService needs to be properly shutdown
ExecutorService executor = Executors.newFixedThreadPool(4);
Callable<String> task = () -> {
//throw new IllegalStateException("try illegal state exception.");
return "in thread" + Thread.currentThread().getId();
};
try{
for(int i=0; i<100; i++) {
Future<String> future = executor.submit(task);
//.get() the calling thread will be blocked to wait for the result of the future object
System.out.println(future.get(100, TimeUnit.MILLISECONDS)); //can set timeout
}
} finally {
executor.shutdown();//soft shutdown, any pending tasks will continue execution to completion.
}
//create a callable class
class Task implements Callable<String> {
public String call() throws Exception {}
}
//may cancel a waiting / running callable task
futures.forEach(
future -> {
try {
future.get(2000, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException e) {
System.out.println(e.getMessage());
} catch (TimeoutException e) {
System.out.println("Timed out");
future.cancel(true); //true means mayInterruptIfRunning
}
}
);
Barrier and Latch
CountDownLatch: synchronize the begining of subsequent tasks on the last one to complete. Once open CountDownLatch cannot be closed again.
CountDownLatch latch = new CountDownLatch(3);
latch.countDown(); //in worker thread
try {
latch.await(10, TimeUnit.SECONDS);//block until the count reaches 0
server.start();
} catch(InterruptedException e) {
}
BrokenBarrierException is raised if
- a thread is interrupted while waiting
- the barrier is reset while some threads are waiting
// can provide a callback to barrier once it is open
CyclicBarrier barrier = new CyclicBarrier(4, ()-> System.out.println("Barrier opening"));
//in callable task, pass the barrier to the callable task
Task task = new Task(barrier);
barrier.await();