Java FX Platform.runLater(() -> equivalent for long running Tasks - java

I learned that in JavaFX the equivalent of
SwingUtilities.invokeLater(new Runnable() {
public void run() {
dosomething();
}
});
might simply be
Platform.runLater(() ->{ dosomething()};
for a long running task I learned that you need to wrap things with a Task like:
Task<Void> task = new Task<Void>() {
#Override
public Void call() {
dosomething();
}
};
new Thread(task).start();
Now it would be great to be able to have a similar lambda shortcut like
TaskLaunch.start(() -> dosomething());
I found
JAVA FX - Lambda for Task interface
Swing timer alternative for JavaFX and the thread management difference
Thread with Lambda expression
discussing some of the issues around this and tried:
package com.bitplan.task.util;
import java.util.concurrent.Callable;
import javafx.concurrent.Task;
/**
* this is a utility task to launch tasks with lambda expressions
*
* #author wf
*
*/
public class TaskLaunch {
/**
*
* #param callable
* #return the new task
*/
public static <T> Task<T> task(Callable<T> callable) {
Task<T> task = new Task<T>() {
#Override
public T call() throws Exception {
return callable.call();
}
};
return task;
}
}
with a JUnit test:
Integer counter=0;
boolean running=false;
public Integer increment() {
running=true;
while (running) {
counter++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
return counter;
}
/**
* #throws Exception
*/
#Test
public void testTaskLaunch() throws Exception {
// https://stackoverflow.com/questions/30089593/java-fx-lambda-for-task-interface
Task<Integer> task=TaskLaunch.task(() -> increment());
try {
Thread.sleep(20);
} catch (InterruptedException e) {
//
}
running=false;
assertTrue(task.get()>10);
}
Which doesn't quite do what I'd like to see yet. The issue seems to be that
the lambda expression runs in the same Thread and the
new Thread(task).start();
part needs to be integrated.
What is needed to get (at least close to) the short one liner mentioned above?
Is a
TaskLaunch.start(() -> dosomething());
feasible?
based on #Damianos proposal https://stackoverflow.com/a/44817217/1497139
I tried:
package com.bitplan.task;
import java.util.concurrent.Callable;
import javafx.concurrent.Task;
/**
* this is a utility task to launch tasks with lambda expressions
*
* #author wf
*
*/
public class TaskLaunch<T> {
Thread thread;
Task<T> task;
Callable<T> callable;
Throwable throwable;
Class<T> clazz;
public Thread getThread() {
return thread;
}
public void setThread(Thread thread) {
this.thread = thread;
}
public Task<T> getTask() {
return task;
}
public void setTask(Task<T> task) {
this.task = task;
}
public Callable<T> getCallable() {
return callable;
}
public void setCallable(Callable<T> callable) {
this.callable = callable;
}
public Throwable getThrowable() {
return throwable;
}
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}
public Class<T> getClazz() {
return clazz;
}
public void setClazz(Class<T> clazz) {
this.clazz = clazz;
}
/**
* construct me from a callable
*
* #param callable
*/
public TaskLaunch(Callable<T> callable, Class<T> clazz) {
this.callable = callable;
this.task = task(callable);
this.clazz = clazz;
}
/**
*
* #param callable
* #return the new task
*/
public static <T> Task<T> task(Callable<T> callable) {
Task<T> task = new Task<T>() {
#Override
public T call() throws Exception {
return callable.call();
}
};
return task;
}
/**
* start
*/
public void start() {
thread = new Thread(task);
thread.start();
}
/**
* start the given callable
* #param callable
* #param clazz - the return Type class
* #return - the launch result
*/
#SuppressWarnings({ "unchecked", "rawtypes" })
public static TaskLaunch start(Callable<?> callable, Class<?> clazz) {
TaskLaunch<?> launch = new TaskLaunch(callable, clazz);
launch.start();
return launch;
}
}
and changed the test to:
/**
* #throws Exception
*/
#SuppressWarnings("unchecked")
#Test
public void testTaskLaunch() throws Exception {
// https://stackoverflow.com/questions/30089593/java-fx-lambda-for-task-interface
TaskLaunch<Integer> launch = TaskLaunch.start(()->increment(),Integer.class);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
//
}
running=false;
assertTrue(launch.getTask().get()>10);
}
This is close to what i am up to but I get:
java.lang.IllegalStateException: Toolkit not initialized
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
at javafx.application.Platform.runLater(Platform.java:83)
at javafx.concurrent.Task.runLater(Task.java:1225)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1417)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:745)
At least TaskLaunch now wraps:
Thread
task
callable
a potential Exception/Throwable
the runtime class of the result of the Task
Some of these 5 items might be redundant and available from the standard java concepts. I think at least its handy to have quick access to these after running things from a one liner.
Hope this gets to a working state and thanks for the help!

Just new Thread(() -> dosomething()).start() should do the trick

This is sort of a traditional XY problem.
A Task is much more than just a background thread, hence for this you can use regular threads. It's the beauty of the properties!
The real benefit of using Task is that all state changes and progress updates can safely be observed and bound to a live scene, while doing all the background work on a different thread. It's the work of the class to do the heavy-lifting and call Platform.runLater.
The reason you need a subclass and not a runnable is so you can call its protected updateXxx() methods without worrying for threading issues.
With this said, you'll have no benefit if this would've been a single line code. For this use simple threads.
Hope this helps.

Doing this will cause you to lose the ability to update stuff back to the UI thread natively supported by Task class. On the other hand, I do agree this can be useful if you want to do something in background in "do-and-forget" style.
The problem is just like what you said - you didn't add new Thead() and Thread.start() in. Do this:
public static void runInBackground(Runnable runnable) {
Task<Void> task = new Task<>() {
#Override
public Void call() throws Exception {
runnable.run();
return null;
}
};
new Thead(task).start();
}
runInBackground(() -> System.out.println(Thread.currentThread().hashCode()));
Note that your Task can no longer be non-void, because it cannot return anything back now. Your lambda needs to be able to reference the Task object to return a result asynchronously - that is never going to be possible using lambda.

The answer is now in the question based on Damianos hint.
The workaround for the exception I found is
com.sun.javafx.application.PlatformImpl.startup(() -> {
});
But seems a little bit hacky ...

Related

Get result from FutureTask after canceling it

Consider a long running computation inside Callable instance.
And consider that the result of this computation can have some precision depending on computation time, i.e.: if task will be cancled than it should return what is computed so far before canceling (for example, we have a conveyor of irrational numbers calculating).
It is desirable to implement this paradigm using standard java concurency utils, e.g.
Callable<ValuableResult> task = new Callable<>() { ... };
Future<ValuableResult> future = Executors.newSingleThreadExecutor().submit(task);
try {
return future.get(timeout, TimeUnit.SECONDS);
} catch (TimeoutException te) {
future.cancel(true);
// HERE! Get what was computed so far
}
It seems, that without full reimplementing of Future and ThreadPoolExecutor interfaces this issue can not be solved. Are any convient existing tools for that in Java 1.7?
Instead of canceling it through the Future's API, tell it to finish through a mechanism of your own (such as a long that you pass into the constructor, which tells it how long to run before returning normally; or an AtomicBoolean you set to true).
Keep in mind that once the task actually starts, cancel (true) doesn't magically stop it. All it does then is to interrupt the thread. There are a few methods that check this flag and throw InterruptedException, but otherwise you'll have to manually check the isInterrupted flag. So, given that you need to code that cooperative mechanism anyway, why not just make it one that better suits your requirements?
Well, it seems to me, that the most simple way in this case is to prepare some final ResultWrapper object, which will be passed inside this Callable instance:
final ValuableResultWrapper wrapper = new ValuableResultWrapper();
final CountDownLatch latch = new CountDownLatch(1);
Callable<ValuableResultWrapper> task = new Callable<>() {
...
wrapper.setValue(...); // here we set what we have computed so far
latch.countDown();
return wrapper;
...
};
Future<ValuableResultWrapper> future = Executors.newSingleThreadExecutor().submit(task);
try {
return future.get(timeout, TimeUnit.SECONDS);
} catch (TimeoutException te) {
future.cancel(true);
// HERE! Get what was computed so far
latch.await();
return wrapper;
}
UPD: In such implemetation (which becomes to complicated) we have to introduce some kind of latch (CountDownLatch in my example) to be sure, that task will be completed before we done return wrapper;
CompletionSerivce is a more powerful than only FutureTask and in many case it's more suitable. I get some idea from it to solve the problem. Besides, its subclass public ExecutorCompletionService is simple than FutureTask, just including a few lines code. It's easy to read. So I modify the class to get partly computed result. A satisfying solution for me, after all, it looks simple and clear.
Demo code:
CompletionService<List<DeviceInfo>> completionService =
new MyCompletionService<>(Executors.newCachedThreadPool());
Future task = completionService.submit(detector);
try {
LogHelper.i(TAG, "result 111: " );
Future<List<DeviceInfo>> result = completionService.take();
LogHelper.i(TAG, "result: " + result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
This is the class code:
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
/**
* This is a CompletionService like java.util.ExecutorCompletionService, but we can get partly computed result
* from our FutureTask which returned from submit, even we cancel or interrupt it.
* Besides, CompletionService can ensure that the FutureTask is done when we get from take or poll method.
*/
public class MyCompletionService<V> implements CompletionService<V> {
private final Executor executor;
private final AbstractExecutorService aes;
private final BlockingQueue<Future<V>> completionQueue;
/**
* FutureTask extension to enqueue upon completion.
*/
private static class QueueingFuture<V> extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task,
BlockingQueue<Future<V>> completionQueue) {
super(task, null);
this.task = task;
this.completionQueue = completionQueue;
}
private final Future<V> task;
private final BlockingQueue<Future<V>> completionQueue;
protected void done() { completionQueue.add(task); }
}
private static class DoneFutureTask<V> extends FutureTask<V> {
private Object outcome;
DoneFutureTask(Callable<V> task) {
super(task);
}
DoneFutureTask(Runnable task, V result) {
super(task, result);
}
#Override
protected void set(V v) {
super.set(v);
outcome = v;
}
#Override
public V get() throws InterruptedException, ExecutionException {
try {
return super.get();
} catch (CancellationException e) {
return (V)outcome;
}
}
}
private RunnableFuture<V> newTaskFor(Callable<V> task) {
return new DoneFutureTask<V>(task);
}
private RunnableFuture<V> newTaskFor(Runnable task, V result) {
return new DoneFutureTask<V>(task, result);
}
/**
* Creates an MyCompletionService using the supplied
* executor for base task execution and a
* {#link LinkedBlockingQueue} as a completion queue.
*
* #param executor the executor to use
* #throws NullPointerException if executor is {#code null}
*/
public MyCompletionService(Executor executor) {
if (executor == null)
throw new NullPointerException();
this.executor = executor;
this.aes = (executor instanceof AbstractExecutorService) ?
(AbstractExecutorService) executor : null;
this.completionQueue = new LinkedBlockingQueue<Future<V>>();
}
/**
* Creates an MyCompletionService using the supplied
* executor for base task execution and the supplied queue as its
* completion queue.
*
* #param executor the executor to use
* #param completionQueue the queue to use as the completion queue
* normally one dedicated for use by this service. This
* queue is treated as unbounded -- failed attempted
* {#code Queue.add} operations for completed tasks cause
* them not to be retrievable.
* #throws NullPointerException if executor or completionQueue are {#code null}
*/
public MyCompletionService(Executor executor,
BlockingQueue<Future<V>> completionQueue) {
if (executor == null || completionQueue == null)
throw new NullPointerException();
this.executor = executor;
this.aes = (executor instanceof AbstractExecutorService) ?
(AbstractExecutorService) executor : null;
this.completionQueue = completionQueue;
}
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture<V>(f, completionQueue));
return f;
}
public Future<V> submit(Runnable task, V result) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task, result);
executor.execute(new QueueingFuture<V>(f, completionQueue));
return f;
}
public Future<V> take() throws InterruptedException {
return completionQueue.take();
}
public Future<V> poll() {
return completionQueue.poll();
}
public Future<V> poll(long timeout, TimeUnit unit)
throws InterruptedException {
return completionQueue.poll(timeout, unit);
}
}

Create a new Event Handler and Source

I have a User Interface(UI) class. It creates some thread (lets call it T) to do some work. I want my UI class to be notified when T is done working.
I think I need to create an event handler in UI class (among onClick() etc) and trigger it from T.
Question: Is this possible ? How ?
//to be clear, UI class does already have some event Handlers which are triggered by functions I didn't write. like onClick() , etc.
This is a fairly common requirement as you generally want to be doing as little as possible on the UI thread.
If you are using swing, have a look at the SwingWorker class. If you are not using swing, you might want to have a look at ExecutorService and FutureTask.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class Futures {
public static void main(String[] args) {
UI ui = new UI();
FutureHandle<String> handle = new FutureHandle<String>(new BigJob());
FutureHandle<String> handle2 = new FutureHandle<String>(new BigJob());
ui.doUIStuff("Things can happen on the UI thread");
ui.startHeavyLiftingJob(handle);
ui.doUIStuff("I've got a big job running, but I'm still responsive");
ui.startHeavyLiftingJob(handle2);
}
/**
* Your UI class. Don't want to do anything big
* on the UI's thread.
*/
static class UI implements Listener<String> {
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
public void doUIStuff(String msg) {
System.out.println(msg);
}
public void startHeavyLiftingJob(FutureHandle<String> handle) {
System.out.println("Starting background task");
handle.setListener(this);
threadPool.execute(handle);
}
public void callback(String result) {
System.out.println("Ooh, result ready: " + result);
}
}
/**
* A handle on a future which makes a callback to a listener
* when the callable task is done.
*/
static class FutureHandle<V> extends FutureTask<V> {
private Listener<V> listener;
public FutureHandle(Callable<V> callable) {
super(callable);
}
#Override
protected void done() {
try {
listener.callback(get());
} catch (InterruptedException e) {
//handle execution getting interrupted
} catch (ExecutionException e) {
//handle error in execution
}
}
public void setListener(Listener<V> listener) {
this.listener = listener;
}
}
/**
* Class that represents something you don't want to do on the UI thread.
*/
static class BigJob implements Callable<String> {
public String call() throws Exception {
Thread.sleep(2000);
return "big job has finished";
}
}
interface Listener<V> {
public void callback(V result);
}
}

Java: ExecutorService thread synchronization with CountDownLatch causes dead lock?

I have written a game of life for programming practice. There are 3 different implementations of the generator. First: One main thread + N sub threads, Second: SwingWorker + N sub threads, Third: SwingWorker + ExecutorService.
N is the number of availableProcessors or user defined.
The first two implementations runs fine, with one and more threads.
The implementation with the ExecutorServise runs fine with one thread, but locks with more than one. I tried everything, but i can't get the solution.
Here the code of the fine workling implementation (second one):
package example.generator;
import javax.swing.SwingWorker;
/**
* AbstractGenerator implementation 2: SwingWorker + sub threads.
*
* #author Dima
*/
public final class WorldGenerator2 extends AbstractGenerator {
/**
* Constructor.
* #param gamePanel The game panel
*/
public WorldGenerator2() {
super();
}
/* (non-Javadoc)
* #see main.generator.AbstractGenerator#startGenerationProcess()
*/
#Override
protected void startGenerationProcess() {
final SwingWorker<Void, Void> worker = this.createWorker();
worker.execute();
}
/**
* Creates a swing worker for the generation process.
* #return The swing worker
*/
private SwingWorker<Void, Void> createWorker() {
return new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws InterruptedException {
WorldGenerator2.this.generationProcessing();
return null;
}
};
}
/* (non-Javadoc)
* #see main.generator.AbstractGenerator#startFirstStep()
*/
#Override
public void startFirstStep() throws InterruptedException {
this.getQueue().addAll(this.getLivingCells());
for (int i = 0; i < this.getCoresToUse(); i++) {
final Thread thread = new Thread() {
#Override
public void run() {
WorldGenerator2.this.fistStepProcessing();
}
};
thread.start();
thread.join();
}
}
/* (non-Javadoc)
* #see main.generator.AbstractGenerator#startSecondStep()
*/
#Override
protected void startSecondStep() throws InterruptedException {
this.getQueue().addAll(this.getCellsToCheck());
for (int i = 0; i < this.getCoresToUse(); i++) {
final Thread thread = new Thread() {
#Override
public void run() {
WorldGenerator2.this.secondStepProcessing();
}
};
thread.start();
thread.join();
}
}
}
Here is the code of the not working implementation with executor service:
package example.generator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.SwingWorker;
/**
* AbstractGenerator implementation 3: SwingWorker + ExecutorService.
*
* #author Dima
*/
public final class WorldGenerator3 extends AbstractGenerator {
private CountDownLatch countDownLatch;
private ExecutorService executor;
/**
* Constructor.
* #param gamePanel The game panel
*/
public WorldGenerator3() {
super();
}
/* (non-Javadoc)
* #see main.generator.AbstractGenerator#startGenerationProcess()
*/
#Override
protected void startGenerationProcess() {
this.executor = Executors.newFixedThreadPool(this.getCoresToUse());
final SwingWorker<Void, Void> worker = this.createWorker();
worker.execute();
}
/**
* Creates a swing worker for the generation process.
* #return The swing worker
*/
private SwingWorker<Void, Void> createWorker() {
return new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws InterruptedException {
WorldGenerator3.this.generationProcessing();
return null;
}
};
}
/* (non-Javadoc)
* #see main.generator.AbstractGenerator#startFirstStep()
*/
#Override
public void startFirstStep() throws InterruptedException {
this.getQueue().addAll(this.getLivingCells());
this.countDownLatch = new CountDownLatch(this.getCoresToUse());
for (int i = 0; i < this.getCoresToUse(); i++) {
this.executor.execute(new Runnable() {
#Override
public void run() {
WorldGenerator3.this.fistStepProcessing();
WorldGenerator3.this.countDownLatch.countDown();
}
});
}
this.countDownLatch.await();
}
/* (non-Javadoc)
* #see main.generator.AbstractGenerator#startSecondStep()
*/
#Override
protected void startSecondStep() throws InterruptedException {
this.getQueue().addAll(this.getCellsToCheck());
this.countDownLatch = new CountDownLatch(this.getCoresToUse());
for (int i = 0; i < this.getCoresToUse(); i++) {
this.executor.execute(new Runnable() {
#Override
public void run() {
WorldGenerator3.this.secondStepProcessing();
WorldGenerator3.this.countDownLatch.countDown();
}
});
}
this.countDownLatch.await();
}
}
Here you can download, a sample of my application, with a small launcher. it prints only the result of a iteration on the console: Link
Now my code looks like this:
/* (non-Javadoc)
* #see main.generator.AbstractGenerator#startFirstStep()
*/
#Override
public void startFirstStep() throws InterruptedException {
this.getQueue().addAll(this.getLivingCells());
final ArrayList<Callable<Void>> list = new ArrayList<Callable<Void>>(this.getCoresToUse());
for (int i = 0; i < this.getCoresToUse(); i++) {
list.add(new Callable<Void>() {
#Override
public Void call() throws Exception {
WorldGenerator3.this.fistStepProcessing();
return null;
}
}
);
}
this.executor.invokeAll(list);
}
But here is again the same problem. If I run it with one core (thread) there are no problems. If I set the number of cores to more than one, it locks. In my first question there is a link to a example, which you can run (in eclipse). Maybe I overlook something in the previous code.
I find your usage of Executors facilities a little bit odd...
I.e. the idea is to have Executor with a pool of threads, size of which usually is related to number of cores your CPU supports.
Then you submit whatever number of parallel tasks to the Executor, letting it to decide what to execute when and on which available Thread from its pool.
As for the CountDownLatch... Why not use ExecutorService.invokeAll? This method will block untill all submitted tasks are completed or timeout is reached. So it will do counting of the work left on your behalf.
Or a CompletionService which "decouples the production of new asynchronous tasks from the consumption of the results of completed tasks" if you want to consume Task result as soon as it becomes available i.e. not wait for all tasks to complete first.
Something like
private static final int WORKER_THREAD_COUNT_DEFAULT = Runtime.getRuntime().availableProcessors() * 2;
ExecutorService executor = Executors.newFixedThreadPool(WORKER_THREAD_COUNT);
// your tasks may or may not return result so consuming invokeAll return value may not be necessary in your case
List<Future<T>> futuresResult = executor.invokeAll(tasksToRunInParallel, EXECUTE_TIMEOUT,
TimeUnit.SECONDS);
In all variants you are executing threads in serial rather than parallel because you join and await inside the for-loop. That means that the for-loop cannot move on to the next iteration until the thread just started is complete. This amounts to having only one thread live at any given time -- either the main thread or the one thread created in the current loop iteration. If you want to join on multiple threads, you must collect the refs to them and then, outside the loop where you started them all, enter another loop where you join on each one.
As for using CountDownLatch in the Executors variant, what was said for threads goes for the latch here: don't use an instance var; use a local list that collects all latches and await them in a separate loop.
But, you shouldn't really be using the CountDownLatch in the first place: you should put all your parallel tasks in a list of Callables and call ExecutorService.invokeAll with it. It will automatically block until all the tasks are done.

Why is UncaughtExceptionHandler not called by ExecutorService?

I've stumbled upon a problem, that can be summarized as follows:
When I create the thread manually (i.e. by instantiating java.lang.Thread) the UncaughtExceptionHandler is called appropriately. However, when I use an ExecutorService with a ThreadFactory the handler is ommited. What did I miss?
public class ThreadStudy {
private static final int THREAD_POOL_SIZE = 1;
public static void main(String[] args) {
// create uncaught exception handler
final UncaughtExceptionHandler exceptionHandler = new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
synchronized (this) {
System.err.println("Uncaught exception in thread '" + t.getName() + "': " + e.getMessage());
}
}
};
// create thread factory
ThreadFactory threadFactory = new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
// System.out.println("creating pooled thread");
final Thread thread = new Thread(r);
thread.setUncaughtExceptionHandler(exceptionHandler);
return thread;
}
};
// create Threadpool
ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE, threadFactory);
// create Runnable
Runnable runnable = new Runnable() {
#Override
public void run() {
// System.out.println("A runnable runs...");
throw new RuntimeException("Error in Runnable");
}
};
// create Callable
Callable<Integer> callable = new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// System.out.println("A callable runs...");
throw new Exception("Error in Callable");
}
};
// a) submitting Runnable to threadpool
threadPool.submit(runnable);
// b) submit Callable to threadpool
threadPool.submit(callable);
// c) create a thread for runnable manually
final Thread thread_r = new Thread(runnable, "manually-created-thread");
thread_r.setUncaughtExceptionHandler(exceptionHandler);
thread_r.start();
threadPool.shutdown();
System.out.println("Done.");
}
}
I expect: Three times the message "Uncaught exception..."
I get: The message once (triggered by the manually created thread).
Reproduced with Java 1.6 on Windows 7 and Mac OS X 10.5.
Because the exception does not go uncaught.
The Thread that your ThreadFactory produces is not given your Runnable or Callable directly. Instead, the Runnable that you get is an internal Worker class, for example see ThreadPoolExecutor$Worker. Try System.out.println() on the Runnable given to newThread in your example.
This Worker catches any RuntimeExceptions from your submitted job.
You can get the exception in the ThreadPoolExecutor#afterExecute method.
Exceptions which are thrown by tasks submitted to ExecutorService#submit get wrapped into an ExcecutionException and are rethrown by the Future.get() method. This is, because the executor considers the exception as part of the result of the task.
If you however submit a task via the execute() method which originates from the Executor interface, the UncaughtExceptionHandler is notified.
Quote from the book Java Concurrency in Practice(page 163),hope this helps
Somewhat confusingly, exceptions thrown from tasks make it to the uncaught
exception handler only for tasks submitted with execute; for tasks submitted
with submit, any thrown exception, checked or not, is considered to be part of the
task’s return status. If a task submitted with submit terminates with an exception,
it is rethrown by Future.get, wrapped in an ExecutionException.
Here is the example:
public class Main {
public static void main(String[] args){
ThreadFactory factory = new ThreadFactory(){
#Override
public Thread newThread(Runnable r) {
// TODO Auto-generated method stub
final Thread thread =new Thread(r);
thread.setUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
// TODO Auto-generated method stub
System.out.println("in exception handler");
}
});
return thread;
}
};
ExecutorService pool=Executors.newSingleThreadExecutor(factory);
pool.execute(new testTask());
}
private static class TestTask implements Runnable {
#Override
public void run() {
// TODO Auto-generated method stub
throw new RuntimeException();
}
}
I use execute to submit the task and the console outputs "in exception handler"
I just browsed through my old questions and thought I might share the solution I implemented in case it helps someone (or I missed a bug).
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.Callable;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* #author Mike Herzog, 2009
*/
public class ExceptionHandlingExecuterService extends ScheduledThreadPoolExecutor {
/** My ExceptionHandler */
private final UncaughtExceptionHandler exceptionHandler;
/**
* Encapsulating a task and enable exception handling.
* <p>
* <i>NB:</i> We need this since {#link ExecutorService}s ignore the
* {#link UncaughtExceptionHandler} of the {#link ThreadFactory}.
*
* #param <V> The result type returned by this FutureTask's get method.
*/
private class ExceptionHandlingFutureTask<V> extends FutureTask<V> implements RunnableScheduledFuture<V> {
/** Encapsulated Task */
private final RunnableScheduledFuture<V> task;
/**
* Encapsulate a {#link Callable}.
*
* #param callable
* #param task
*/
public ExceptionHandlingFutureTask(Callable<V> callable, RunnableScheduledFuture<V> task) {
super(callable);
this.task = task;
}
/**
* Encapsulate a {#link Runnable}.
*
* #param runnable
* #param result
* #param task
*/
public ExceptionHandlingFutureTask(Runnable runnable, RunnableScheduledFuture<V> task) {
super(runnable, null);
this.task = task;
}
/*
* (non-Javadoc)
* #see java.util.concurrent.FutureTask#done() The actual exception
* handling magic.
*/
#Override
protected void done() {
// super.done(); // does nothing
try {
get();
} catch (ExecutionException e) {
if (exceptionHandler != null) {
exceptionHandler.uncaughtException(null, e.getCause());
}
} catch (Exception e) {
// never mind cancelation or interruption...
}
}
#Override
public boolean isPeriodic() {
return this.task.isPeriodic();
}
#Override
public long getDelay(TimeUnit unit) {
return task.getDelay(unit);
}
#Override
public int compareTo(Delayed other) {
return task.compareTo(other);
}
}
/**
* #param corePoolSize The number of threads to keep in the pool, even if
* they are idle.
* #param eh Receiver for unhandled exceptions. <i>NB:</i> The thread
* reference will always be <code>null</code>.
*/
public ExceptionHandlingExecuterService(int corePoolSize, UncaughtExceptionHandler eh) {
super(corePoolSize);
this.exceptionHandler = eh;
}
#Override
protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task) {
return new ExceptionHandlingFutureTask<V>(callable, task);
}
#Override
protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task) {
return new ExceptionHandlingFutureTask<V>(runnable, task);
}
}
In addition to Thilos answer: I've written a post about this behavior, if one wants to have it explained a little bit more verbose: https://ewirch.github.io/2013/12/a-executor-is-not-a-thread.html.
Here is a excerpts from the article:
A Thread is capable of processing only one Runable in general. When the Thread.run() method exits the Thread dies. The ThreadPoolExecutor implements a trick to make a Thread process multiple Runnables: it uses a own Runnable implementation. The threads are being started with a Runnable implementation which fetches other Runanbles (your Runnables) from the ExecutorService and executes them: ThreadPoolExecutor -> Thread -> Worker -> YourRunnable. When a uncaught exception occurs in your Runnable implementation it ends up in the finally block of Worker.run(). In this finally block the Worker class tells the ThreadPoolExecutor that it “finished” the work. The exception did not yet arrive at the Thread class but ThreadPoolExecutor already registered the worker as idle.
And here’s where the fun begins. The awaitTermination() method will be invoked when all Runnables have been passed to the Executor. This happens very quickly so that probably not one of the Runnables finished their work. A Worker will switch to “idle” if a exception occurs, before the Exception reaches the Thread class. If the situation is similar for the other threads (or if they finished their work), all Workers signal “idle” and awaitTermination() returns. The main thread reaches the code line where it checks the size of the collected exception list. And this may happen before any (or some) of the Threads had the chance to call the UncaughtExceptionHandler. It depends on the order of execution if or how many exceptions will be added to the list of uncaught exceptions, before the main thread reads it.
A very unexpected behavior. But I won’t leave you without a working solution. So let’s make it work.
We are lucky that the ThreadPoolExecutor class was designed for extensibility. There is a empty protected method afterExecute(Runnable r, Throwable t). This will be invoked directly after the run() method of our Runnable before the worker signals that it finished the work. The correct solution is to extend the ThreadPoolExecutor to handle uncaught exceptions:
public class ExceptionAwareThreadPoolExecutor extends ThreadPoolExecutor {
private final List<Throwable> uncaughtExceptions =
Collections.synchronizedList(new LinkedList<Throwable>());
#Override
protected void afterExecute(final Runnable r, final Throwable t) {
if (t != null) uncaughtExceptions.add(t);
}
public List<Throwable> getUncaughtExceptions() {
return Collections.unmodifiableList(uncaughtExceptions);
}
}
There is a little bit of a workaround.
In your run method, you can catch every exception, and later on do something like this (ex: in a finally block)
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), ex);
//or, same effect:
Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), ex);
This will "ensure a firing" of the current exception as thrown to your uncoughtExceptionHandler (or to the defualt uncought exception handler).
You can always rethrow catched exceptions for pool worker.

How to notify all observers without holding the thread?

I have a thread inside a class like this-
import java.util.Observable;
public class Download extends Observable {
private int state = 0;
private final Thread myThread = new Thread(() -> {
/*
some work to do here
*/
setChanged();
notifyObservers(state);
});
public void download(int state) {
if (!myThread.isAlive()) {
this.state = state;
myThread.start();
}
}
public Thread getThread() {
return myThread;
}
public static void MyMethod() throws InterruptedException {
Download down = new Download();
down.addObserver((Observable ob, Object dat) -> {
System.out.println(ob);
if ((int) dat == 1) {
down.download(2);
} else {
System.out.println("success");
}
});
down.download(1);
down.getThread().join();
}
public static void main() throws InterruptedException {
MyMethod();
}
}
The problem is I never get it to print the "success" message.
I assume, it is because all observers are being notified from inside of MyThread. So when down.download(2) is called from the observer inside MyMethod(), the previous thread is still running and the call is ignored.
How can I notify all observers from the main thread, not from the myThread?
You are calling down.download(2) from within the execution of MyThread, therefore the thread is still alive which means that your download method does nothing because of if(!myThread.isAlive()).
I would recommend you to use the Executor framework and Listenable Futures from Guava instead of creating threads manually. Example code from the Guava wiki:
ListeningExecutorService service =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
public Explosion call() {
return pushBigRedButton();
}
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
// we want this handler to run immediately after we push the big red button!
public void onSuccess(Explosion explosion) {
walkAwayFrom(explosion);
}
public void onFailure(Throwable thrown) {
battleArchNemesis(); // escaped the explosion!
}
});
Note that Futures.addCallback(..) also has an overload which allows you to determine which executor should execute the callback, this seems to be what you want.

Categories