Java concurrent programming (1) canceling or disabling concurrent programs, java concurrency
I. Cancel the task on Close 1. Interrupt the Thread
1. Each thread has a boolean interrupt state. True indicates the interruption status.
Interrupt: Issue interrupt request; isInterrupt: Return interrupt status; interrupted: Clear interrupt status
2. The blocking method in JVM checks the thread interruption status. The response method is to clear the interruption status,An InterruptedException exception is thrown.Indicates that the blocking operation is terminated. However, the JVM does not guarantee when the blocking method detects the thread interruption status.
3. Interruption understanding: A running thread is not actually interrupted, but a request is sent. The specific interruption is handled by the task itself.
It is usually the best way to cancel a thread through interruption.
Public class PrimeProducer extends Thread {private final BlockingQueue <BigInteger> queue; PrimeProducer (BlockingQueue <BigInteger> queue) {this. queue = queue;} public void run () {try {BigInteger p = BigInteger. ONE; while (! Thread. currentThread (). isInterrupted () queue. put (p = p. nextProbablePrime ();} catch (InterruptedException consumed) {/* Allow thread to exit * // If an interrupt exception is caught, the thread exits by itself} public void cancel () {interrupt ();}}
2. Non-disruptive blocking interruption
For example, for Socket I/O operations, even if an interrupt request is set, it will not be interrupted, but close the Socket will throw an exception to achieve the interruption effect. Therefore, we needOverride interrupt method
// Custom callable implementation class public abstract class SocketUsingTask <T> implements CancellableTask <T> {private Socket socket; protected synchronized void setSocket (Socket s) {socket = s ;} // cancel the public synchronized void cancel () {try {if (socket! = Null) socket. close () ;}catch (IOException ignored) {}// method for creating an instance public RunnableFuture <T> newTask () {return new FutureTask <T> (this) {public boolean cancel (boolean mayInterruptIfRunning) {try {SocketUsingTask. this. cancel ();} finally {return super. cancel (mayInterruptIfRunning) ;}}}}// custom callable interface CancellableTask <T> extends Callable <T> {void cancel (); runnableFuture <T> newTask ();} // custom execution pool class CancellingExecutor extends ThreadPoolExecutor {...... // rewrite newTaskFor to return your Callable protected <T> RunnableFuture <T> newTaskFor (Callable <T> callable) {if (callable instanceof CancellableTask) return (CancellableTask <T>) callable ). newTask (); else return super. newTaskFor (callable );}}
3. Cancel a timing task through custom
Private static final ScheduledExecutorService cancelExec = newScheduledThreadPool (1 ); /***** @ param r Task * @ param timeout * @ param unit TimeUnit * @ throws InterruptedException */public static void timedRun (final Runnable r, long timeout, timeUnit) throws InterruptedException {class RethrowableTask implements Runnable {// use a volatile variable to store whether the thread is abnormal private volatile Throwable t; public void Run () {try {r. run () ;}catch (Throwable t) {this. t = t ;}} private void rethrow () {if (t! = Null) throw launderThrowable (t) ;}} RethrowableTask task = new RethrowableTask (); final Thread taskThread = new Thread (task); taskThread. start (); // The execution thread is interrupted after the timeout unit. schedule ()-> taskThread. interrupt (), timeout, unit); // wait at any time. If the thread does not respond to the interruption, wait for the timeout time of the task thread through join and return to the caller thread taskThread. join (unit. toMillis (timeout); // if the task thread has an exception, a task is thrown. rethrow ();}
Note: dependent on join, task time-out join exit and normal task join cannot be judged
4. Use Futrue to cancel timing tasks
Private static final ExecutorService taskExec = Executors. newCachedThreadPool (); public static void timedRun (Runnable r, long timeout, TimeUnit unit) throws InterruptedException {Future <?> Task = taskExec. submit (r); try {// Futrue. get (time-out time), capture the corresponding exceptions to handle timing operation and cancel the task. get (timeout, unit);} catch (TimeoutException e) {// task will be canceled below} catch (ExecutionException e) {// exception thrown in task; rethrow throw launderThrowable (e. getCause ();} finally {// Harmless if task already completed task. cancel (true); // interrupt if running }}2. Stop thread-based services
1. Generally, services cannot be directly interrupted, resulting in service data loss.
2. The thread pool service cannot be directly interrupted.
1. Log Service
Standard producer and consumer model
Public class LogService {private final BlockingQueue <String> queue; private final LoggerThread loggerThread; private final PrintWriter writer; private boolean isShutdown; private int reservations; public LogService (Writer writer) {this. queue = new LinkedBlockingQueue <String> (); this. loggerThread = new LoggerThread (); this. writer = new PrintWriter (writer);} public void start () {loggerThread. start ();} public void stop () {synchronized (this) {isShutdown = true;} loggerThread. interrupt (); // issue interrupt} public void log (String msg) throws InterruptedException {synchronized (this) {if (isShutdown) {throw new IllegalStateException (/*... */);} + + reservations; // The number of correctly stored logs in the queue} queue. put (msg); // put logs into the queue} private class LoggerThread extends Thread {public void run () {try {while (true) {try {synchronized (LogService. this) {if (isShutdown & reservations = 0) {break ;}} String msg = queue. take (); synchronized (LogService. this) {-- reservations;} writer. println (msg);} catch (InterruptedException e) {/* retry * // capture the interrupt request. However, in order to output the remaining logs, no processing is performed, close until the counter = 0} finally {writer. close ();}}}}
2. ExecutorService interrupted
ShutDown and shutDownNow
Generally, ExecetorService is encapsulated, such as LogService, so that it has its own life cycle method.
Limitations of shutDownNow:If you do not know the thread status in the current pool, the task not started is returned, but the task not started is not returned.
Public class TrackingExecutor extends actexecutorservice {private final ExecutorService exec; private final Set <Runnable> tasksCancelledAtShutdown = Collections. synchronizedSet (new HashSet <Runnable> (); public TrackingExecutor () {exec = Executors. newSingleThreadExecutor ();}/* public TrackingExecutor (ExecutorService exec) {this.exe c = exec;} */public void shutdown () {exec. shutdown ();} pu Blic List <Runnable> shutdownNow () {return exec. shutdownNow ();} public boolean isShutdown () {return exec. isShutdown ();} public boolean isTerminated () {return exec. isTerminated ();} public boolean awaitTermination (long timeout, TimeUnit unit) throws InterruptedException {return exec. awaitTermination (timeout, unit);} public List <Runnable> getCancelledTasks () {if (! Exec. isTerminated () throw new IllegalStateException (/*... */); return new ArrayList <Runnable> (tasksCancelledAtShutdown);} public void execute (final Runnable runnable) {exec.exe cute (new Runnable () {public void run () {try {runnable. run () ;}finally {if (isShutdown () & Thread. currentThread (). isInterrupted () tasksCancelledAtShutdown. add (runnable) ;}}) ;}@ Test public void test () throws InterruptedException {ExecutorService executorService = Executors. newSingleThreadExecutor (); TrackingExecutor trackingExecutor = new TrackingExecutor (); trackingExecutor.exe cute (new Runnable () {@ Override public void run () {try {Thread. sleep (1, 2000); System. err. println ("123123");} catch (InterruptedException e) {Thread. currentThread (). interrupt (); // set the status or continue to throw, and process e. printStackTrace () ;}finally {}}); List <Runnable> runnables = trackingExecutor. shutdownNow (); trackingExecutor. awaitTermination (10, TimeUnit. SECONDS); List <Runnable> cancelledTasks = trackingExecutor. getCancelledTasks (); System. err. println (cancelledTasks. size ());}}
3. Handling abnormal thread termination 1. Thread termination caused by exceptions not captured
1. Manually handle uncaptured exceptions
2. Through the Thread API UncaughExceptionHandler, we can detect that a Thread has encountered an uncaptured Thread and causes an exception to terminate.
Note: The exception stack information is output to the console by default; Custom Handler: implements Thread. UncaughExceptionHandler override method
You can set each thread or a global ThreadGroup.
Thread. setUncaughtExceptionHandler/Thread. setDefaultUncaughtExceptionHandler
2. JVM exit and daemon thread