jaulib v1.3.0
Jau Support Library (C++, Java, ..)
RunnableTask.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 * Copyright (c) 2010 Gothel Software e.K.
5 * Copyright (c) 2010 JogAmp Community.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27package org.jau.util.parallel;
28
29import java.io.PrintStream;
30
31import org.jau.lang.InterruptSource;
32import org.jau.lang.InterruptedRuntimeException;
33
34/**
35 * Helper class to provide a Runnable queue implementation with a Runnable wrapper
36 * which notifies after execution for the <code>invokeAndWait()</code> semantics.
37 */
38public class RunnableTask extends TaskBase {
39 protected final Runnable runnable;
40
41 /**
42 * Invokes <code>runnable</code> on the current {@link Thread}.
43 * @param runnable the {@link Runnable} to execute on the current thread.
44 * The runnable <b>must exit</b>, i.e. not loop forever.
45 * @return the newly created and invoked {@link RunnableTask}
46 * @since 0.3.0
47 */
48 public static RunnableTask invokeOnCurrentThread(final Runnable runnable) {
49 final RunnableTask rt = new RunnableTask( runnable, null, false, null );
50 rt.run();
51 return rt;
52 }
53
54 /**
55 * Invokes <code>runnable</code> on a new {@link InterruptSource.Thread},
56 * see {@link InterruptSource.Thread#Thread(ThreadGroup, Runnable, String)} for details.
57 * @param tg the {@link ThreadGroup} for the new thread, maybe <code>null</code>
58 * @param threadName the name for the new thread, maybe <code>null</code>
59 * @param waitUntilDone if <code>true</code>, waits until <code>runnable</code> execution is completed, otherwise returns immediately.
60 * @param runnable the {@link Runnable} to execute on the new thread. If <code>waitUntilDone</code> is <code>true</code>,
61 * the runnable <b>must exit</b>, i.e. not loop forever.
62 * @return the newly created and invoked {@link RunnableTask}
63 * @since 0.3.0
64 */
65 public static RunnableTask invokeOnNewThread(final ThreadGroup tg, final String threadName,
66 final boolean waitUntilDone, final Runnable runnable) {
67 final RunnableTask rt;
68 if( !waitUntilDone ) {
69 rt = new RunnableTask( runnable, null, true, System.err );
70 final InterruptSource.Thread t = InterruptSource.Thread.create(tg, rt, threadName);
71 t.start();
72 } else {
73 final Object sync = new Object();
74 rt = new RunnableTask( runnable, sync, true, null );
75 final InterruptSource.Thread t = InterruptSource.Thread.create(tg, rt, threadName);
76 synchronized(sync) {
77 t.start();
78 while( rt.isInQueue() ) {
79 try {
80 sync.wait();
81 } catch (final InterruptedException ie) {
82 throw new InterruptedRuntimeException(ie);
83 }
84 final Throwable throwable = rt.getThrowable();
85 if(null!=throwable) {
86 throw new RuntimeException(throwable);
87 }
88 }
89 }
90 }
91 return rt;
92 }
93
94 /**
95 * Create a RunnableTask object w/ synchronization,
96 * ie. suitable for <code>invokeAndWait()</code>, i.e. {@link #invoke(boolean, Runnable) invoke(true, runnable)}.
97 *
98 * @param runnable The user action
99 * @param syncObject The synchronization object if caller wait until <code>runnable</code> execution is completed,
100 * or <code>null</code> if waiting is not desired.
101 * @param catchExceptions Influence an occurring exception during <code>runnable</code> execution.
102 * If <code>true</code>, the exception is silenced and can be retrieved via {@link #getThrowable()},
103 * otherwise the exception is thrown.
104 * @param exceptionOut If not <code>null</code>, exceptions are written to this {@link PrintStream}.
105 */
106 public RunnableTask(final Runnable runnable, final Object syncObject, final boolean catchExceptions, final PrintStream exceptionOut) {
108 this.runnable = runnable ;
109 }
110
111 /** Return the user action */
112 public final Runnable getRunnable() {
113 return runnable;
114 }
115
116 @Override
117 public final void run() {
118 execThread = Thread.currentThread();
119
120 runnableException = null;
121 tStarted = System.currentTimeMillis();
122 if(null == syncObject) {
123 try {
124 runnable.run();
125 } catch (final Throwable t) {
127 if(null != exceptionOut) {
128 exceptionOut.println("RunnableTask.run(): "+getExceptionOutIntro()+" exception occured on thread "+Thread.currentThread().getName()+": "+toString());
130 runnableException.printStackTrace(exceptionOut);
131 }
132 if(!catchExceptions) {
133 throw new RuntimeException(runnableException);
134 }
135 } finally {
136 tExecuted = System.currentTimeMillis();
137 isExecuted = true;
138 }
139 } else {
140 synchronized (syncObject) {
141 try {
142 runnable.run();
143 } catch (final Throwable t) {
145 if(null != exceptionOut) {
146 exceptionOut.println("RunnableTask.run(): "+getExceptionOutIntro()+" exception occured on thread "+Thread.currentThread().getName()+": "+toString());
148 t.printStackTrace(exceptionOut);
149 }
150 if(!catchExceptions) {
151 throw new RuntimeException(runnableException);
152 }
153 } finally {
154 tExecuted = System.currentTimeMillis();
155 isExecuted = true;
156 syncObject.notifyAll();
157 }
158 }
159 }
160 }
161}
162
java.lang.Thread specialization implementing InterruptSource to track java.lang.Thread#interrupt() ca...
static Thread create(final ThreadGroup tg, final Runnable target, final String name)
Depending on whether name is null, either Thread(ThreadGroup, Runnable, String) or Thread(ThreadGroup...
Unchecked exception propagating an InterruptedException where handling of the latter is not desired.
Helper class to provide a Runnable queue implementation with a Runnable wrapper which notifies after ...
static RunnableTask invokeOnCurrentThread(final Runnable runnable)
Invokes runnable on the current Thread.
static RunnableTask invokeOnNewThread(final ThreadGroup tg, final String threadName, final boolean waitUntilDone, final Runnable runnable)
Invokes runnable on a new InterruptSource.Thread, see InterruptSource.Thread#Thread(ThreadGroup,...
RunnableTask(final Runnable runnable, final Object syncObject, final boolean catchExceptions, final PrintStream exceptionOut)
Create a RunnableTask object w/ synchronization, ie.
final Runnable getRunnable()
Return the user action.
Helper class to provide a Runnable queue implementation with a Runnable wrapper which notifies after ...
Definition: TaskBase.java:38
final Throwable getThrowable()
Definition: TaskBase.java:170
final String getExceptionOutIntro()
Definition: TaskBase.java:81
volatile Thread execThread
Definition: TaskBase.java:58
volatile boolean isExecuted
Definition: TaskBase.java:56
final PrintStream exceptionOut
Definition: TaskBase.java:49
Interface exposing java.lang.Thread#interrupt() source, intended for java.lang.Thread specializations...