The Following Code, A ScheduledExecutor has a task. In Production it will have several tasks, but for now I'm testing with one. Anyway, I need to be able to process Exceptions. My code below does this, but causes my GUI to become unresponsive. The line marked appears the be the issue. How can I gather all the Exceptions as they happen?
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
CommandInterface ci = tc.getTask().getCommandInterface();
ScheduledExecutorService scheduler =
taskManager.getComponentInterface().getThreadPool();
ScheduledFuture<?> st = scheduler.schedule(
new TimedRunnable(ci), new Date(
ci.getScheduledDate().getTime()
- System.currentTimeMillis()).getTime(), TimeUnit.MILLISECONDS);
//This line causes blocking ->
SwingUtilities.invokeLater(new AlertRunnable(
taskManager.getComponentInterface().getAlertList(), st));
}
});
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
CommandInterface ci = tc.getTask().getCommandInterface();
taskManagerInterface.getComponentInterface().getThreadPool().schedule(new TimedRunnable(ci, taskManagerInterface.getComponentInterface()), new Date(ci.getScheduledDate().getTime() - System.currentTimeMillis()).getTime(), TimeUnit.MILLISECONDS);
}
});
with timed runnable being:
/**
* This class runs at a specific time.
*/
public static class TimedRunnable implements Runnable, Serializable {
ExecutorService workerExecutor = Executors.newSingleThreadExecutor();
CommandInterface commandInterface;
ComponentInterface componentInterface;
public TimedRunnable(CommandInterface commandInterface, ComponentInterface componentInterface) {
this.commandInterface = commandInterface;
this.componentInterface = componentInterface;
}
#Override
public void run() {
//submit the callable to the progressHelper
Future future = workerExecutor.submit(new Callable() {
#Override
public Object call() throws Exception {
try {
ReturnInterface returnInterface = (ReturnInterface) commandInterface.call();
returnInterface.submitResult();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return null;
}
});
try {
Object get = future.get();
} catch (InterruptedException | ExecutionException ex) {
Throwable cause = ex.getCause();
Throwable cause1 = cause.getCause();
if (cause1 instanceof CommandInterfaceException) {
System.out.println("[MyItemTree].scheduleTask Cause 1= COMMANDINTERFACE EXCEPTION");
this.componentInterface.getAlertList().addAlert(((CommandInterfaceException) cause1).getResolverFormInterface());
}
}
}
}
Related
I read a lot of post about ExecutorService, but I can't find the way of doing what I need.
I need some concurrent threads. When any of them throw a custom exception all the remaining tasks are canceled.
This is an example of what I did. The task are working concurrent, but aren't interrupted on exception.
public class Main {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
List<Future> futures = new ArrayList<Future>();
futures.add(executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
Thread.sleep(5000);
System.out.println("Task 1 done");
return null;
}
}));
futures.add(executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
Thread.sleep(2000);
System.out.println("Task 2 done");
if (true) {
throw new CustomException("Error on task 2");
}
return null;
}
}));
executorService.shutdown();
try {
executeFutures(futures);
} catch (CustomException ex) {
System.out.println("Received:" + ex.getMessage());
executorService.shutdownNow();
}
}
private static void executeFutures(List<Future> futures) throws CustomException {
try {
for (Future f : futures) {
f.get();
}
} catch (ExecutionException | InterruptedException e) {
if (e.getCause() instanceof CustomException) {
throw (CustomException) e.getCause();
}
}
}
}
This is the output:
Task 2 done //exception is thrown here but task1 continue.
Task 1 done
Received:Error on task 2
Any help will be appreciated.
Your problem is due to the fact that the method executeFutures make the main thread call f.get() on the first Future instance corresponding to the long task, which makes it wait the duration of the task so at least 5 seconds whatever happens. Once done it will then call f.get() on the second Future which is already over so it gets immediately the CustomException from the ExecutionException and calls executorService.shutdownNow() but it is already too late as there is no more tasks left to interrupt.
What you could do, is to use a decorator of type Callable that will automatically shutdown the thread pool when a CustomException is thrown, this way the thread pool will be shutdown directly by the thread that has executed the task that throws the exception instead of using the main thread.
Something like this:
public class AutoShutdown<V> implements Callable<V> {
private final ExecutorService executorService;
private final Callable<V> task;
public AutoShutdown(final ExecutorService executorService, final Callable<V> task) {
this.executorService = executorService;
this.task = task;
}
#Override
public V call() throws Exception {
try {
return task.call();
} catch (CustomException e) {
executorService.shutdownNow();
throw e;
}
}
}
Then you will need to submit your tasks through the decorator as next:
futures.add(
executorService.submit(
new AutoShutdown<>(
executorService,
new Callable<Void>() {
public Void call() throws Exception {
Thread.sleep(5000);
System.out.println("Task 1 done");
return null;
}
}
)
)
);
futures.add(
executorService.submit(
new AutoShutdown<>(
executorService,
new Callable<Void>() {
public Void call() throws Exception {
Thread.sleep(2000);
System.out.println("Task 2 done");
if (true) {
throw new CustomException("Error on task 2");
}
return null;
}
}
)
)
);
Output:
Task 2 done
As you can see in the output, the task one has been interrupted soon enough.
The message "Received:Error on task 2" was not thrown, so it looks
like a successful execution, and is not the case
No it is only because the first call to f.get() throws an InterruptedException as expected which makes it exit from executeFutures because the catch is performed outside the loop, move it inside the loop as next:
private static void executeFutures(List<Future> futures) throws CustomException {
for (Future f : futures) {
try {
f.get();
} catch (ExecutionException | InterruptedException e) {
if (e.getCause() instanceof CustomException) {
throw (CustomException) e.getCause();
}
}
}
}
Output:
Task 2 done
Received:Error on task 2
i'm trying create a thread, which return a value, the process is running correctly but my screen is still locked. I want a thread that return a value but my main thread continues running.
I've done that:
public void showPartidas(int maximumDistance){
ExecutorService es = Executors.newFixedThreadPool(1);
Future<ArrayList<Partida>> partidas= es.submit(new FilterPartidas(maximumDistance));
try {
loadInListView(partidas.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
es.shutdown();
}
class FilterPartidas implements Callable<ArrayList<Partida> > {
private final int distance;
private ArrayList<Partida> partidas;
FilterPartidas(int distance) {
this.distance = distance;
}
#Override
public ArrayList<Partida> call() throws Exception {
partidas=null;
Download load = new Download();
Date fecha = new Date();
DateFormat fechaFormat = new SimpleDateFormat("yyyy-MM-dd");
String query = "select * from partidas where fecha >='"+fechaFormat.format(fecha)+"'";
partidas=load.obtainPartidas(query, distance, myPosition);
return partidas;
}
}
partidas.get() action is the cause that main thread is waiting for the completion of Callable method in executor. If you want main thread are still running during Callable action execution you must place partidas.get() action into dedicated separate thread e.g.:
replace
Future<ArrayList<Partida>> partidas= es.submit(new FilterPartidas(maximumDistance));
try {
loadInListView(partidas.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
into
final Future<ArrayList<Partida>> partidas= es.submit(new FilterPartidas(maximumDistance));
new Thread(new Runnable() {
#Override
public void run() {
try {
loadInListView(partidas.get());
} catch (InterruptedEArrayList<Partida>xception e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}).start();
or similar action with threads (maybe using executor, Runnable, etc).
Or you can change you logic (if possible) and hide call to method from Callable into Runnable class. E,g.:
ExecutorService es = Executors.newFixedThreadPool(1);
es.submit(new Runnable() {
#Override
public void run() {
ArrayList<Partida> partidas = logic from you Callable call;
loadInListView(partidas);
}
});
I have an executor service that accepts new tasks :
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 1000; i++) {
try{
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(task);
}
catch (ExecutionException e) {
System.out.println(e.getMessage());
}
}
My problem is that I'm not able to catch any exception thrown by the Runnable, unless I'm doing this :
Future<?> future = executor.submit(task);
try {
future.get();
} catch (Exception e) {
System.out.println("############### exception :" + e.getMessage());
}
The problem is that future.get() is blocking, so if I 'm not able to run my tasks asynchronously and my tasks will not run in parallel, but sequentially.
I would like to be able to use Java 8 and CompletableFuture but I can't ...
Do you have any other idea?
Thanks
The code inside the Runnable is executing on a separate thread, so you must handle its exceptions inside the run() method.
If you need to gather all the exceptions for later handling, I would do something like this:
ExecutorService executor = Executors.newFixedThreadPool(1000);
final List<Exception> exceptions = // a place to put exceptions
Collections.synchronizedList(new ArrayList<Exception>());
for (int i = 0; i < 1000; i++) {
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
exceptions.add(e); // save the exception for later
}
}
};
executor.submit(task);
}
// wait for all the tasks to finish, then...
for (Exception e: exceptions) {
// whatever you want to do
}
Otherwise, if you just want to get information about each exception as it occurs:
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
e.printStackTrace();
}
}
};
Anything you need to do after the task asynchronously can be added to the task itself.
for (int i = 0; i < 1000; i++) {
final Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(new Runnable() {
public void run() {
try {
task.run();
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
or you combine them into one Runnable.
This may not be the best solution but we could make a parent Runnable which will do the work of the actual Runnable. The parent will catch all the exceptions you need to know about. Here is slight convoluted approach:
public static void main(String[] args){
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 5; i++) {
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
ParentRunnable t = new ParentRunnable();
t.setRunnable(task, i);
executor.submit(t);
}
}
static class ParentRunnable implements Runnable {
Runnable r;
int index;
public void setRunnable(Runnable r, int index){
this.r = r;
this.index = index;
}
public void run() {
try{
System.out.println("\n" + index + "\n");
r.run();
}catch(Exception e){
e.printStackTrace();
}
}
}
I have a requirement threading where I need to initiate a thread which will run continuously doing some DB operations . A second thread will be present which needs to run for every 30 secs. The job of the second thread will be killing the first thread and start a new instance of the first thread.
I tried several ways to achieve this but I am not able to do the same.
public class ThreadMain {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException{
final CyclicBarrier gate = new CyclicBarrier(3);
Thread t1 = new Thread(){
public void run(){
try {
gate.await();
while(true)
{
System.out.println("Thread1");
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
Thread t2 = new Thread(){
public void run(){
try {
gate.await();
while(true)
{
System.out.println("Continiously running thread:-Thread2");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
t1.start();
t2.start();
This seems to work nicely:
// Thread that runs forever.
volatile static Thread forEverThread = null;
static class ForEver implements Runnable {
#Override
public void run() {
try {
while (true) {
Thread.sleep(1000);
System.out.println("For Ever!");
}
} catch (InterruptedException ex) {
// Just quit if I was interrupted.
}
}
}
// Stop the thread if it is running.
private static void stopForeverThread() throws InterruptedException {
// Skip if non-existent.
if (forEverThread != null) {
// Make sure no-one else is already doing it.
synchronized (forEverThread) {
// Still not null?
if (forEverThread != null) {
// Interrupt it.
forEverThread.interrupt();
// Wait for it to finish.
forEverThread.join();
// Clear it.
forEverThread = null;
}
}
}
}
private static void restartForeverThread() throws InterruptedException {
System.out.println("Restarting...");
// Stop it if it is running.
stopForeverThread();
// Start it again.
forEverThread = new Thread(new ForEver());
forEverThread.start();
System.out.println("Restarted");
}
public static void start() throws InterruptedException {
// Start it all up.
restartForeverThread();
// Timed event to restart it.
Timer restartTimer = new Timer(true);
restartTimer.scheduleAtFixedRate(
new TimerTask() {
#Override
public void run() {
try {
// Restart every few seconds.
restartForeverThread();
} catch (InterruptedException ex) {
// We were interrupted during restart - Log it.
}
}
// Every few seconds.
}, 0, 10 * 1000);
}
public static void main(String args[]) {
try {
// Start it all up.
start();
// Hang around for a while - to see what happens.
Thread.sleep(60 * 1000);
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
If your database task is interruptible (i.e. it reacts on thread interruption and hence can be cancelled by that), the best strategy is to use an ScheduledExecutorService for both, the database task itself and the restart task that runs periodically.
Note that task and thread are two different things: While a task is a piece of work that should be run, threads are the mechanism to do this in parallel.
static class DatabaseTask implements Runnable {
public void run() {
...
}
}
static class RestartTask implements Runnable {
private final ExecutorService executor;
private volatile Future<Void> future;
public RestartTask(ExecutorService executor) {
this.executor = executor;
}
public void run() {
if (future != null) {
future.cancel(true);
}
future = executor.submit(new DatabaseTask());
}
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new RestartTask(executor), 0, 30, TimeUnit.SECONDS);
Note that if your DatabaseTask is NOT sensitive to thread interruption and continues to perform database operations, the number of threads executing database tasks will grow continously - probably not what you want. So make sure, all blocking database operations are either interruptible, or terminate within a reasonable amount of time.
Why we can't see the stacktrace in this example ?
public class NoStackTraceTester implements Runnable {
private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> lifeCheckFuture;
#Override
public void run() {
lifeCheckFuture = startLifecheck();
}
private ScheduledFuture<?> startLifecheck()
{
Runnable lifeCheck = new Runnable()
{
#Override
public void run()
{
System.out.println("sending lifecheck ...");
throw new RuntimeException("bang!");
}
};
return scheduler.scheduleAtFixedRate(lifeCheck, 1000, 1000, TimeUnit.MILLISECONDS);
}
public static void main(String[] args) {
new NoStackTraceTester().run();
}
}
If you try to comment the exception you will the the repeative task of the lifecheck function.
But if an exception is thrown, thread stop but with no detail :(
Do you have an idea why ?
An ExecutorService places any captured Throwable in the Future object. If you inspect this you can see what exception was thrown. This is not always desirable so you may have to catch and handle or log any exception in the run() method.
Note: once an exception escapes, the task is not repeated again.
Runnable lifeCheck = new Runnable() {
#Override
public void run() {
try {
System.out.println("sending lifecheck ...");
throw new RuntimeException("bang!");
} catch(Throwable t) {
// handle or log Throwable
}
}
};
If you want an exception report, you must insert handling code yourself. The ExecutorService will not automatically send the exception trace to the standard output, and it is very good that it doesn't since this is rarely what we need in production code.
Basically, this is the approach:
public void run()
{
try {
System.out.println("sending lifecheck ...");
throw new RuntimeException("bang!");
} catch (Throwable t) { t.printStackTrace(); }
}
The afterExecute() method in ThreadPoolExecutor can be overridden:
class MyThreadPoolExecutor extends ThreadPoolExecutor {
public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
#Override
public void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
// If submit() method is called instead of execute()
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException e) {
t = e;
} catch (ExecutionException e) {
t = e.getCause();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
if (t != null) {
// Exception occurred
System.err.println("Uncaught exception is detected! " + t
+ " st: " + Arrays.toString(t.getStackTrace()));
}
// ... Perform cleanup actions
}
}
final class MyTask implements Runnable {
#Override public void run() {
System.out.println("My task is started running...");
// ...
throw new ArithmeticException(); // uncatched exception
// ...
}
}
public class ThreadPoolExecutorHandler {
public static void main(String[] args) {
// Create a fixed thread pool executor
ExecutorService threadPool = new MyThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>());
threadPool.execute(new MyTask());
// ...
}
}
source: https://medium.com/#aozturk/how-to-handle-uncaught-exceptions-in-java-abf819347906 (Please note, I modified the code posted here to not re-execute as the question only asks for stacktrace printing)