Java Concurrency Programming Combat: Seventh----Cancel and close

Source: Internet
Author: User
Tags finally block throwable volatile

Java does not provide any mechanism to safely terminate a thread (although the Thread.stop and suspend methods provide such a mechanism, but because of a flaw, you should avoid using

Interrupt: A collaboration mechanism that enables one thread to terminate the current work of another thread

stopping immediately causes the shared data structure to be in an inconsistent state , and when it needs to be stopped, an interrupt request is made, and the thread that is asked to interrupt finishes his current task and determines whether to stop

I. CANCELLATION of MISSION

If the external code can be placed in the "done" state before an operation is completed, the operation can be canceled . (User request cancellation, time-limited actions < concurrency lookup results, one thread found can cancel other threads >, application events, errors, shutdown)

Cancellation Policy: Define the "how" and "when" and "what" of the cancel operation in detail, that is, how the other code requests that the task be canceled, when the task checks if cancellation has been requested, and what action should be taken in response to the cancellation request

Example: setting the volatile variable to a cancellation flag, checking before each execution

1 private volatile Boolean canceled; 2      3     @Override 4 public     void Run () {5         BigInteger p = biginteger.one, 6 while         (!canceled) {7             p = p. Nextprobableprime (); 8             synchronized (this) {//sync add Prime 9                 Primes.add (p);             }11         }12     }

Note: This is a problematic cancellation method, and if the thread blocks after the add operation, it will not run to the code that verifies the blocking state even if the cancellation state is set, so it will block forever

1. Interruption

  This mechanism can be used by a thread to notify another thread, telling it to stop the current work as appropriate or possible, and to perform other tasks instead. (It is not appropriate to use interrupts outside of cancellation)

Calling interrupt does not mean that the target thread is immediately stopped from working, but only the message that the request was interrupted is passed. Will interrupt itself at the next cancellation point, such as wait, sleep,join, etc.

1 public class Thread {2 public      void interrupt () {...} interrupt target thread, resume interrupt State 3 public      Boolean isinterrupted () {...} returns the interrupt status of the target thread 4 public      static Boolean interrupted () {...} clears the interrupt state of the current thread and returns the value before it (for a break state has been set, but has not yet been interrupted)5 ...      6  }

Blocking library methods, such as Thread.Sleep and object.wait, will check when a thread is interrupted and return early when it is discovered. The actions they perform in response to an outage include clearing the interrupt state, throwing a interruptedexception, indicating that the blocking operation ended prematurely due to an outage .

    • The detected interrupt is displayed! Thread.CurrentThread (). isinterrupted () after launch
    • Blocking method Interruptedexception after catching the exit

2. Interrupt policy--Specify how the thread interprets an interrupt request--what should be done when an interrupt request is found

Because each thread has its own interrupt policy, this thread should not be interrupted unless you know what the interrupt means for that thread.

3. Response Interruption

    • Passing exception (throws Interruptedexception)

    • Restores the interrupt state so that the upper code of the call stack can handle it. (Thread.CurrentThread (). interrupt ();)

4, through the future to achieve cancellation

Boolean Cancel (Boolean mayinterruptifrunning);

    • If the task has completed, or has been canceled, or cannot be canceled for some other reason, the attempt will fail and return false
    • When you call Cancel, if the call succeeds and the task has not been started, the task will never run
    • If the task is already executed, the mayinterruptifrunning parameter determines whether the interrupt operation is issued to the thread performing the task

5, handling non-disruptive blocking --for some blocking operations, just set the interrupt state

    • Java.io the synchronous socket I/O in the package. Although both read and write methods in InputStream and OutputStream do not respond to interrupts, the underlying socket can be turned off to cause a socketexception to be thrown by a thread that is blocked by executing a read or write method.
    • java.io the synchronous I/O in the package. When you break a thread that is waiting on a interruptiblechannel, Will throw Closedbyinterruptedexception) and close the link (this will also cause other threads that are blocked on this link to also throw closedbyinterruptexception). When a interruptiblechannel is closed, all threads that are blocked on the link operation are thrown asynchronouscloseexception. Most of the standard channel implementations are interruptiblechannel.
    • The selector asynchronous I/O. If a thread blocks while calling the Selector.select method (in Java.nio.channels), calling the close or wakeup method causes the thread to throw closedselectorexception and return early.
    • Gets a lock. If a thread is blocked because it waits for a built-in lock, the interrupt cannot be responded to because the thread thinks it is definitely getting a lock, so the interrupt request will not be heeded. However, the Lockinterruptibly method is provided in the lock class, which allows you to still respond to interrupts while waiting for a lock.
1//Overwrite interrupt method issue Interrupt Request    2  @Override 3 public     void Interrupt () {4         try {5             socket.close (); Close socket 6         } catch before interrupt (IOException e) {7              8         } finally{9             super.interrupt ();         }11     }

6, the use of newtaskfor to encapsulate non-standard cancellation

Second, stop thread-based services

Applications typically create thread-based services, such as thread pooling. These services typically have a longer time than the method that created it.

    • The thread needs to end the service exit---cannot stop the thread by a preemptive method, so they need to end themselves
    • The thread cannot be manipulated unless it owns a thread. For example, a thread break or the priority of modifying threads, etc.
    • The thread pool is the owner of its worker thread, and if you want to break those threads, you should use the thread pool
    • Applications can own services, and services can own worker threads, but applications cannot have worker threads, so applications cannot directly stop worker threads.

The service should have a life-cycle approach to shutting down its own and the threads he owns

    • The life cycle method should be provided for the lifetime of the service to be greater than the time of the method that created the thread.
    • Executorservice provided by shutdown (), Shutdownnow ()

1. Example: Log service

 1//LogWriter is a thread-based service, but not a completed Service 2 public class LogWriter {3//log Cache 4 private final blockingqueue<string& Gt Queue 5 Private final Loggerthread logger;//log write thread 6 private static final int capacity = 1000;         7 8 public LogWriter (writer writer) {9 this.queue = new linkedblockingqueue<string> (capacity); 10 This.logger = new Loggerthread (writer),}12 public void Start () {Logger.start ();}  14 15//The application logs the log into the log cache. public void log (String msg) throws Interruptedexception {queue.put (msg); 18 }19 20//Log write thread, this is a multi-producer, single consumer design of the private class Loggerthread extends thread {private final Printwrite R writer;23 Public Loggerthread (writer writer) {this.writer = new PrintWriter (writer, true);//AUT oflush25}26 public void Run () {try {) (true) W Riter.println (Queue.take ()); (InterruptedexceptioN ignored) {~} finally {writer.close (); 33}34}35}36} 

Note: can break the blocked take () method to stop the log thread (consumer thread), but the producer does not have a dedicated thread and cannot be canceled

 1//Log service, provide logging services, and have management Service lifecycle related methods 2 public class Logservice {3 private final blockingqueue<string> queue; 4 private Final Loggerthread loggerthread;//Journal write thread 5 private final printwriter writer; 6 Private Boolean isshutdown;//service shutdown indicates the number of log message stores in the 7//queue. Can't we get it through queue.size ()? 8//Why do you need this? See back 9 private int reservations;10 one public Logservice (writer writer) {this.queue = new Li Nkedblockingqueue<string> (); this.loggerthread = new Loggerthread (); this.writer = n EW PrintWriter (writer); 15 16}17 18//Start log service public void Start () {Loggerthread.sta                      RT (); 21}22 23//Shut down log service public void Stop () {synchronized (this) {26 /*27 * For thread visibility, be sure to add synchronization here, of course, volatile also, 28 * But the following method also requires atomicity, so here is the direct use of the SYNCHR onized,29 * But not set IsShutDownRighteousness for volatile30 */31 IsShutDown = true;32}33//to journal line Cheng Interrupt request Loggerthread.interrupt (); 35}36 37//For application invocation, used to store log information to be logged in the log cache the public void Lo                       G (String msg) throws Interruptedexception {synchronized (this) {40/*41                      * If the application makes a service shutdown request, there is no accept log, but instead directly 42 * Throws an exception to let the application know 43 */44                      if (IsShutDown) New IllegalStateException (/* Log service closed */); 46 /*47 * Because the queue is a thread-safe blocking queue, synchronization is not required (synchronization can also be 48 * but concurrency efficiency will decrease, so it is placed outside the synchronization block). But here it is. 49 * The sequence of operations consists of two operations: that is, the IsShutDown is judged first, then the message is placed in the cache 50 *, and if Queue.put (msg) is placed outside the synchronization, In the multi-line Cheng 51 *, Loggerthread in the queue.size () = = 0 will be inaccurate, 52 * to want to queue.put out of sync, but also              to Queue.size () calculate the accuracy, the 53         * A variable reservations is used to record the number of log bars in the cache, 54 * This solves the problem of low efficiency of synchronous queue and resolves the security problem, 55 * This is really the two worlds. */57//queue.put (msg); ++reservations;  Storage Plus 159}60 queue.put (msg);}62 + private class Loggerthread extends Thread                                    {67 public void Run () {$ try {$ true}                                                  try {synchronized (logservice.this) {69                                                  Queue.size70 cannot be used here because the queue is not synchronized if (IsShutDown && queue.size () = = 0) 71 72//If it is closed and the log letter in the cache                                   Log thread if (isshutdown && reservations = 0) 74                      break;75}76 Str                                                  ing msg = queue.take (); synchronized (logservice.this) {78                                           --reservations;79}80                                    WRITER.PRINTLN (msg); Bayi} catch (Interruptedexception e) {/* Retry */82                             }83}84} finally {85 Writer.close (); 86}87}88}89}

Note: An atomic way to check the shutdown request and conditionally increment a counter to "keep" the right to submit a message

2. Close Executorservice

  Shutdown (): Start one order close, perform a previously submitted task, and perform a task that runs out

Shutdownnow (): An attempt was made to stop all the tasks that were being performed (the interrupt operation syntax is issued to them, there is no guarantee that the task thread being processed can be stopped, but will try it out), and the waiting task is paused and the list of tasks awaiting execution is returned.

Executorservice is closed and rejectedexecutionexception exception is thrown when a task is submitted to it

3. "Poison Pill" object--stop immediately when you get this object

  All work submitted before the "poison pill" object is submitted will be processed, and the producer shall not submit any work after submitting the "poison pill" object

4. Only one service is performed once

If a method needs to handle a batch of tasks and returns after all the tasks have been processed, a private executor can be used to simplify the lifecycle management of the service, where the life cycle of the executor is controlled by this method.

1 Boolean checkmail (set<string> hosts, long timeout, timeunit unit) 2         throws interruptedexception {3 Executorse Rvice exec = Executors.newcachedthreadpool (); 4//cannot use volatile hasnewmail, because also need to modify 5     final Atomicboolean hasnewmail = new Atomicboolean (false) in anonymous; 6     try {7 For         (final String host:hosts)//loop retrieve each host 8             Exec.execute (new Runnable () {//Perform task 9 public                 Void Run () {Ten                    I F (Checkmail (host))                        Hasnewmail.set (true);                 }13             });     finally {         exec.shutdown ();// Because Executorservice is only served in this method, you can close the         exec.awaittermination (timeout, unit) after completion, and//wait for the task to complete and return     if the timeout is not completed }18     return Hasnewmail.get (); 19}

5, the limitations of shutdown

We cannot use the usual method to find out which tasks have started but are not yet finished. This means that we cannot know the status of the task being executed during the shutdown process unless the task itself performs some sort of check

 1 public class Trackingexecutor extends Abstractexecutorservice {2 private final executorservice exec; 3 private Final set<runnable> Taskscancelledatshutdown = 4 Collections.synchronizedset (new Hashset<runnable&gt ;()); 5 6 Public Trackingexecutor (Executorservice exec) {7 this.exec = exec, 8} 9 public List<runna Ble> Getcancelledtasks () {//returns the canceled task one by one if (!exec.isterminated ())//If the Shutdownnow is not called or the call is not completed when the N     EW illegalstateexception (/*...*/); return new arraylist<runnable> (Taskscancelledatshutdown); 14}15 16  public void execute (final Runnable Runnable) {Exec.execute (new Runnable () {in public void run () {try {runnable.run (); 21/* Reference: HTTP://BLOG.CSDN.NET/C                              oslay/article/details/4803879522 * In essence, there will be a thread security problem, there are competitive conditions, such as the program just 23 * Good to run here, i.e. task Task (Run method) just ran out, when the outside call 24 * Shutdownnow (), then the following finally block judgment will be error, display 25 * The task has been completed, but the judgment given is canceled. If you want to be safe, it's not 26 * should let Shutdownnow before the Run method runs complete with the following judgment before calling. We want 27 * Place Runnable.run () with the following if in a synchronous block, and also put the Shutdownnow call Synchronization block and with the front if the same monitor lock, 29 * This seems to be solved, do not know to not. The book also did not say can solve, 30 * Just said there is this problem! But in turn, if this is really synchronous, it will take 31 * performance problems, because what all the tasks will be executed in a string, this will also be a * EXECU Torservice thread pool What do you do? I think that's why the author says 33 * This is the inevitable competitive condition. */35} Final                             ly {36//If the Shutdownnow is called and the running task is interrupted if (IsShutDown () 38 && Thread.CurrentThread (). isinterrupted ()) Taskscancelledatshutdown.add (runnable);//Record the canceled task 40                }41}42}); 43}44//Delegate other methods in Executorservice to Exec45}  

Third, handling the abnormal thread termination

  Starts another thread in one thread, throws an exception in another thread, and if it is not caught, the exception is not passed to the parent thread

Any code can throw a runtimeexception. Whenever another method is called, be suspicious of its behavior, do not blindly assume that it will return normally, or it will throw a checked exception declared in the method prototype

1//If the task throws a run-time exception, it will allow the thread to terminate, but the framework will be notified first: the thread has terminated 2 public void run () {///worker thread implementation 3     throwable thrown = null; 4     try {5< C4/>while (!isinterrupted ()) 6             RunTask (Gettaskfromworkqueue ()); 7     } catch (Throwable e) {//For security, all exceptions caught 8         Thrown = e;//Reserved exception information 9     } finally {         threadexited (this, thrown);//re-throw the exception to the framework and end the worker thread one by one     }12}
The thread that did not catch the exception

Uncaughtexceptionhandler is provided in the thread API, which detects when a thread is terminated due to an uncaught exception

In long-running applications, the same exception handler is typically specified for all uncaught exceptions, and the processor logs the exception information to at least one log.

public class Uehlogger implements Thread.uncaughtexceptionhandler {public    void uncaughtexception (Thread t, Throwable e) {        Logger Logger = Logger.getanonymouslogger ();        Logger.log (Level.severe, "Thread terminated with exception:" + T.getname (), e);}    }

Iv. JVM shutdown

The JVM can either be closed by normal means or forcibly shut down.

    • Normal shutdown: When the last "normal (non-daemon)" thread ends, when someone calls System.exit, or when it is closed by another platform-specific method
    • Forced shutdown: Runtime.halt, this forced shutdown method will not guarantee that closing hooks will be run

1. Close the hook

    • A closed hook is a thread registered through Runnable.addshutdownhook but not yet started.
    • The JVM does not guarantee the call order of closing hooks
    • When all closure hooks are executed, if Runfinalizersonexit is true, then the JVM will run the finalizer (finalize) and then stop
    • The JVM does not stop or break any application threads that are still running when they are shut down. When the JVM eventually ends, these threads will be forcibly ended. If the hook is closed or the finalizer is not completed, the normal shutdown process "hangs" and the JVM must be forcibly shut down. When forcibly closed, only shuts down the JVM and does not run the close hook
    • Closing hooks should be thread-safe
    • Close hooks must exit as soon as they delay the end time of the JVM
public void Start ()//By registering to close the hook, stop log service {    runnable.getruntime (). Addshutdownhook (New Thread () {public        void run ()        {            try{logservice.this.stop ();}            catch (Interruptedexception ignored) {}}}    );

2, daemon thread--a thread to perform some auxiliary work, but there is no hope that this thread will hinder the shutdown of the JVM

Threads can be divided into two types: normal thread and daemon thread. All threads created at the start of the JVM, except the main thread, are daemon threads

The difference between a normal thread and a daemon thread is only the action that occurs when the thread exits. When a thread exits, the JVM checks for other running threads, and if those threads are daemons, the JVM exits gracefully. When the JVM is stopped, all remaining daemons are discarded-neither the finally code block nor the rollback stack is executed, and the JVM simply exits

3, terminator (clean file handle or socket handle, etc.)--Avoid using

The garbage collector makes special handling of objects that define a Finalize method: After the collector releases them, it calls their Finalize method, ensuring that some persisted resources are freed.

By using the finally code block and the explicit Close method, you can better manage resources than using finalizers

Exception: When you need to manage objects, and the resources that the object holds are obtained through local methods

Java Concurrency Programming Combat: Seventh----Cancel and close

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.