Introduction to Java Thread blocking interrupts and Locksupport usage _java

Source: Internet
Author: User
Tags connection pooling sleep volatile
In the Friday and the weekend, work to sneak in, looking at the Java cocurrent also by the way the Thread.Interrupt and Java 5 after the implementation of the Locksupport.


Before introducing, let's throw a few questions.


The relationship between Thread.Interrupt () method and Interruptedexception anomaly? is the interruptedexception exception triggered by the interrupt trigger?


Thread.Interrupt () What state of the thread will interrupt the work? RUNNING or BLOCKING?


General thread programming needs to focus on interrupt interrupts? How do you deal with it generally? What can be used for?


What is the difference between Locksupport.park () and Unpark (), and Object.wait () and notify ()?


What does the blocker object passed by Locksupport.park (object blocker) do?


Locksupport can respond to Thread.Interrupt () events? Throw a Interruptedexception exception?


Does the Thread.Interrupt () process have a corresponding callback function? Similar to hook call?


If you can have a very clear answer, you already know thread.interrupt, you can not look down there.


If it's not clear, take these questions and comb them together.


Several methods of interrupt processing of thread:


public void interrupt (): Executing thread interrupt Event


public boolean isinterrupted (): Checks whether the current thread is in interrupt


public static Boolean Interrupted (): Check whether the current thread is in interrupt and reset the interrupt information. Similar to Resetandget ()


Understand:


1. Each thread has a interrupt status flag bit that indicates whether the current thread is in an interrupted state


2. General call Thread.Interrupt () can be handled in two ways


When a lower-priority block state is encountered, such as object.wait (), Object.sleep (), Object.join (). It will immediately trigger a unblock unblock, and throw a interruptedexception.


In other cases, Thread.Interrupt () only updated the status flag bit. Then your work thread is checked by thread.isinterrrupted (), and you can do the corresponding processing, such as throw interruptedexception or cleanup status, cancel task, etc.


Described in interrupt Javadoc:





Best practices


There's an article on IBM that's pretty good. Java theory and practice:dealing with Interruptedexception, which mentions several best practices for interrupt processing.


Don ' t swallow interrupts (don't eat interrupt, usually two treatments: Continue throw interruptedexception exception. The other is to continue to set the Thread.interupt () abnormal flag bit, so that the next layer to deal with the corresponding.


Copy Code code as follows:

public class Taskrunner implements Runnable {
Private blockingqueue<task> queue;
Public Taskrunner (blockingqueue<task> queue) {
This.queue = queue;
}
public void Run () {
try {
while (true) {
Task task = Queue.take (timeunit.seconds);
Task.execute ();
}
}
catch (Interruptedexception e) {
Restore the interrupted status
Thread.CurrentThread (). interrupt ();
}
}
}



Copy Code code as follows:

public class Taskrunner implements Runnable {
Private blockingqueue<task> queue;
Public Taskrunner (blockingqueue<task> queue) {
This.queue = queue;
}
public void Run () {
try {
while (true) {
Task task = Queue.take (timeunit.seconds);
Task.execute ();
}
}
catch (Interruptedexception e) {
Restore the interrupted status
Thread.CurrentThread (). interrupt ();
}
}
}



Implementing Cancelable Tasks with Interrupt (using Thread.Interrupt () to design and support cancel tasks)


Copy Code code as follows:

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 * *
}
}
public void Cancel () {interrupt ();}//Initiate interrupt
}<span style= "White-space:normal" > </SPAN>



Copy Code code as follows:

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 * *
}
}
public void Cancel () {interrupt ();}//Initiate interrupt
}<span style= "White-space:normal" > </SPAN>



Registering interrupt handling events (abnormal usage)


The normal task design used to process cancel is to check Thread.isinterrupt () in the form of active polling, there is a certain embedding in the business itself, there is a delay, you have to wait until the next checkpoint (who knows when the next checkpoint is, In particular, when a socket.read is performed, a problem with a httpclient timeout has been encountered.


Take a look at, the initiative throws interruptedexception the realization of the exception, draw lessons from the design of the Interruptiblechannel, compare the trickery.


Copy Code code as follows:



Interface Interruptable {//define interruptible interfaces


public void interrupt () throws interruptedexception;


}


Abstract class Interruptsupport implements Interruptable {


Private volatile Boolean interrupted = false;


Private interruptible interruptor = new Interruptible () {


public void interrupt () {


interrupted = true;


InterruptSupport.this.interrupt (); Location 3


}


};


Public Final Boolean execute () throws Interruptedexception {


try {


Blockedon (Interruptor); Location 1


if (Thread.CurrentThread (). isinterrupted ()) {//Immediately be interrupted


Interruptor.interrupt ();


}


Execute business code


Bussiness ();


finally {


Blockedon (NULL); Location 2


}


return interrupted;


}


public abstract void bussiness ();


public abstract void interrupt ();


--Sun.misc.SharedSecrets--


static void Blockedon (Interruptible intr) {//Package-private


Sun.misc.SharedSecrets.getJavaLangAccess (). Blockedon (Thread.CurrentThread (), intr);


}


}





Copy Code code as follows:



Interface Interruptable {//define interruptible interfaces


public void interrupt () throws interruptedexception;


}


Abstract class Interruptsupport implements Interruptable {


Private volatile Boolean interrupted = false;


Private interruptible interruptor = new Interruptible () {


public void interrupt () {


interrupted = true;


InterruptSupport.this.interrupt (); Location 3


}


};


Public Final Boolean execute () throws Interruptedexception {


try {


Blockedon (Interruptor); Location 1


if (Thread.CurrentThread (). isinterrupted ()) {//Immediately be interrupted


Interruptor.interrupt ();


}


Execute business code


Bussiness ();


finally {


Blockedon (NULL); Location 2


}


return interrupted;


}


public abstract void bussiness ();


public abstract void interrupt ();


--Sun.misc.SharedSecrets--


static void Blockedon (Interruptible intr) {//Package-private


Sun.misc.SharedSecrets.getJavaLangAccess (). Blockedon (Thread.CurrentThread (), intr);


}


}





Code description, a few tricky points:


Location 1: Using the Blockedon method provided by sun, bind the corresponding interruptible event handle hook to the specified thread.


Position 2: After executing the code, empty the hook. The impact of the next thread handling event when you avoid using connection pooling.


Location 3: Defines the Interruptible event hook processing method, callback InterruptSupport.this.interrupt () method, subclasses can integrate to implement their own business logic, such as sock flow shutdown and so on.


Use:


Copy Code code as follows:



Class Interruptread extends Interruptsupport {


Private FileInputStream in;


@Override


public void bussiness () {


File File = new file ("/dev/urandom"); Read Linux black hole, never read


try {


in = new FileInputStream (file);


byte[] bytes = new byte[1024];


while (In.read (bytes, 0, 1024) &gt; 0) {


Thread.Sleep (100);


if (thread.interrupted ()) {//previous interrupt Check mode


throw new Interruptedexception ("");


// }


}


catch (Exception e) {


throw new RuntimeException (e);


}


}


Public FileInputStream Getin () {


return in;


}


@Override


public void interrupt () {


try {


In.getchannel (). Close ();


catch (IOException e) {


E.printstacktrace ();


}


}


}


public static void Main (String args[]) throws Exception {


Final Interruptread test = new Interruptread ();


Thread t = new Thread () {


@Override


public void Run () {


Long start = System.currenttimemillis ();


try {


System.out.println ("Interruptread start!");


Test.execute ();


catch (Interruptedexception e) {


System.out.println ("Interruptread end! Cost Time: "+ (System.currenttimemillis ()-start);"


E.printstacktrace ();


}


}


};


T.start ();


Let read execute for 3 seconds first.


Thread.Sleep (3000);


Issue interrupt Interrupt


T.interrupt ();


}





Copy Code code as follows:



Class Interruptread extends Interruptsupport {


Private FileInputStream in;


@Override


public void bussiness () {


File File = new file ("/dev/urandom"); Read Linux black hole, never read


try {


in = new FileInputStream (file);


byte[] bytes = new byte[1024];


while (In.read (bytes, 0, 1024) &gt; 0) {


Thread.Sleep (100);


if (thread.interrupted ()) {//previous interrupt Check mode


throw new Interruptedexception ("");


// }


}


catch (Exception e) {


throw new RuntimeException (e);


}


}


Public FileInputStream Getin () {


return in;


}


@Override


public void interrupt () {


try {


In.getchannel (). Close ();


catch (IOException e) {


E.printstacktrace ();


}


}


}


public static void Main (String args[]) throws Exception {


Final Interruptread test = new Interruptread ();


Thread t = new Thread () {


@Override


public void Run () {


Long start = System.currenttimemillis ();


try {


System.out.println ("Interruptread start!");


Test.execute ();


catch (Interruptedexception e) {


System.out.println ("Interruptread end! Cost Time: "+ (System.currenttimemillis ()-start);"


E.printstacktrace ();


}


}


};


T.start ();


Let read execute for 3 seconds first.


Thread.Sleep (3000);


Issue interrupt Interrupt


T.interrupt ();


}





JDK Source Introduction:


1. Sun provides hooks to view system-related code, line:1125


Copy Code code as follows:

Sun.misc.SharedSecrets.setJavaLangAccess (New sun.misc.JavaLangAccess () {
Public Sun.reflect.ConstantPool Getconstantpool (Class Klass) {
return Klass.getconstantpool ();
}
public void Setannotationtype (Class klass, Annotationtype type) {
Klass.setannotationtype (type);
}
Public Annotationtype Getannotationtype (Class Klass) {
return Klass.getannotationtype ();
}
Public <e extends Enum<e>>
E[] getenumconstantsshared (class<e> Klass) {
return klass.getenumconstantsshared ();
}
public void Blockedon (Thread t, interruptible b) {
T.blockedon (b);
}
});



Copy Code code as follows:

Sun.misc.SharedSecrets.setJavaLangAccess (New sun.misc.JavaLangAccess () {
Public Sun.reflect.ConstantPool Getconstantpool (Class Klass) {
return Klass.getconstantpool ();
}
public void Setannotationtype (Class klass, Annotationtype type) {
Klass.setannotationtype (type);
}
Public Annotationtype Getannotationtype (Class Klass) {
return Klass.getannotationtype ();
}
Public <e extends Enum<e>>
E[] getenumconstantsshared (class<e> Klass) {
return klass.getenumconstantsshared ();
}
public void Blockedon (Thread t, interruptible b) {
T.blockedon (b);
}
});



2. Thread.Interrupt ()


Copy Code code as follows:

public void interrupt () {
if (this!= thread.currentthread ())
CheckAccess ();
Synchronized (Blockerlock) {
Interruptible b = blocker;
if (b!= null) {
Interrupt0 (); Just to set the interrupt flag
B.interrupt (); Callback Hook
Return
}
}
Interrupt0 ();
}



Copy Code code as follows:

public void interrupt () {
if (this!= thread.currentthread ())
CheckAccess ();
Synchronized (Blockerlock) {
Interruptible b = blocker;
if (b!= null) {
Interrupt0 (); Just to set the interrupt flag
B.interrupt (); Callback Hook
Return
}
}
Interrupt0 ();
}



More


For more information on the use of Thread.stop,suspend,resume,interrupt, you can look at Sun's documentation, such as http://download.oracle.com/javase/6/docs/ Technotes/guides/concurrency/threadprimitivedeprecation.html


Finally, to answer some of the previous questions:


Question 1:thread.interrupt () method and interruptedexception anomaly relation? is the interruptedexception exception triggered by the interrupt trigger?


A: Thread.Interrupt () is only in object.wait (). Object.join (), Object.sleep () several methods will actively throw interruptedexception exceptions. And in other blocks common, just by setting the thread of a flag bit information, requires the program to process itself.


Copy Code code as follows:

if (thread.interrupted ())//Clears interrupted status!
throw new Interruptedexception ();



Copy Code code as follows:

if (thread.interrupted ())//Clears interrupted status!
throw new Interruptedexception ();



Question 2:thread.interrupt () What state of the thread will interrupt the work? RUNNING or BLOCKING?


A: The main purpose of the Thread.Interrupt design is to handle the thread in block state, such as wait (), and sleep () state is an example. However, the running state can also be supported when designing to support task Cancel. Examples include object.join () and some NIO channel designs that support interrupt.


Question 3: General thread programming needs to focus on interrupt interrupts? How do you deal with it generally? What can be used for?


A: Interrupt use: unblock operation, support task Cancel, data cleaning and so on.


Question 4:locksupport.park () and Unpark (), and the difference between object.wait () and notify ()?


For:


1. The main body of the face is different. Locksuport mainly for thread feed blocking processing, you can specify the target object blocking the queue, each time you can specify a specific thread wakeup. Object.wait () is an object-latitude, blocking the current thread and waking a single (random) or all threads.


2. The implementation mechanism is different. Although Locksuport can specify the object objects for monitor, and object.wait (), the blocking queues for both are not crossed. You can look at the test examples. Object.notifyall () cannot wake locksupport blocking thread.


What does the blocker object passed by the question 5:locksupport.park (object blocker) do?


A: The corresponding blcoker will be recorded in a parkblocker attribute of thread, which is very convenient to monitor the specific blocking object through the Jstack command.


Copy Code code as follows:

public static void Park (Object blocker) {
Thread t = Thread.CurrentThread ();
Setblocker (t, blocker); Set the value of the Thread.parkblocker property
Unsafe.park (False, 0L);
Setblocker (t, NULL); Clear the value of the Thread.parkblocker property
}



Copy Code code as follows:

public static void Park (Object blocker) {
Thread t = Thread.CurrentThread ();
Setblocker (t, blocker); Set the value of the Thread.parkblocker property
Unsafe.park (False, 0L);
Setblocker (t, NULL); Clear the value of the Thread.parkblocker property
}



The specific Locksupport Javadoc description is also more clear, you can look at:





Problem 6:locksupport can respond to Thread.Interrupt () event? Throw a Interruptedexception exception?


A: Can respond to interrupt events, but will not throw interruptedexception exceptions. For Locksupport support for Thread.interrupte, take a look at the description in Javadoc:





Related test code


Copy Code code as follows:



Package com.agapple.cocurrent;


Import Java.io.File;


Import Java.io.FileInputStream;


Import Java.lang.reflect.Field;


Import Java.util.concurrent.TimeUnit;


Import Java.util.concurrent.locks.LockSupport;


public class Locksupporttest {


private static locksupporttest blocker = new Locksupporttest ();


public static void Main (String args[]) throws Exception {


Locksupporttest ();


Parktest ();


Interruptparktest ();


Interruptsleeptest ();


Interruptwaittest ();


}


/**


* Locksupport.park object, try to get Thread.blocker object, call its single wake


*


* @throws Exception


*/


private static void Locksupporttest () throws Exception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () throws Exception {


Try Sleep 5s


System.out.println ("Blocker");


Locksupport.park (blocker);


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Locksupporttest";


}


});


T.start (); Start Read thread


Thread.Sleep (150);


Synchronized (blocker) {


Field field = Thread.class.getDeclaredField ("Parkblocker");


Field.setaccessible (TRUE);


Object Fblocker = field.get (t);


System.out.println (blocker = = Fblocker);


Thread.Sleep (100);


System.out.println ("Notifyall");


Blocker.notifyall ();


}


}


/**


* Try to interrupt a object.wait (), throw the corresponding interruptedexception exception


*


* @throws interruptedexception


*/


private static void Interruptwaittest () throws Interruptedexception {


Final Object obj = new Object ();


Thread t = dotest (new Testcallback () {


@Override


public void callback () throws Exception {


Try Sleep 5s


Obj.wait ();


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Interruptwaittest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


T.interrupt (); Check to see if the interrupt is in response to park


}


/**


* Try to interrupt a thread.sleep (), throw the corresponding interruptedexception exception


*


* @throws interruptedexception


*/


private static void Interruptsleeptest () throws Interruptedexception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () throws Exception {


Try Sleep 5s


Thread.Sleep (5000);


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Interruptsleeptest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


T.interrupt (); Check to see if the interrupt is in response to park


}


/**


* Try to interrupt a locksupport.park (), will respond but not throw interruptedexception exception


*


* @throws interruptedexception


*/


private static void Interruptparktest () throws Interruptedexception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () {


Try to park your own thread


Locksupport.parknanos (Blocker, TimeUnit.SECONDS.toNanos (5));


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Interruptparktest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


T.interrupt (); Check to see if the interrupt is in response to park


}


/**


* Try to interrupt a locksupport.unpark (), there will be a response


*


* @throws interruptedexception


*/


private static void Parktest () throws Interruptedexception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () {


Try to park your own thread


Locksupport.park (blocker);


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Parktest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


Locksupport.unpark (t);


T.interrupt ();


}


public static Thread Dotest (final testcallback call) {


return new Thread () {


@Override


public void Run () {


File File = new file ("/dev/urandom"); Read Linux black Hole


try {


FileInputStream in = new FileInputStream (file);


byte[] bytes = new byte[1024];


while (In.read (bytes, 0, 1024) &gt; 0) {


if (thread.interrupted ()) {


throw new Interruptedexception ("");


}


System.out.println (Bytes[0]);


Thread.Sleep (100);


Long start = System.currenttimemillis ();


Call.callback ();


System.out.println (Call.getname () + "Callback Finish cost:"


+ (System.currenttimemillis ()-start);


}


catch (Exception e) {


E.printstacktrace ();


}


}


};


}


}


Interface Testcallback {


public void callback () throws Exception;


Public String getName ();


}





Copy Code code as follows:



Package com.agapple.cocurrent;


Import Java.io.File;


Import Java.io.FileInputStream;


Import Java.lang.reflect.Field;


Import Java.util.concurrent.TimeUnit;


Import Java.util.concurrent.locks.LockSupport;


public class Locksupporttest {


private static locksupporttest blocker = new Locksupporttest ();


public static void Main (String args[]) throws Exception {


Locksupporttest ();


Parktest ();


Interruptparktest ();


Interruptsleeptest ();


Interruptwaittest ();


}


/**


* Locksupport.park object, try to get Thread.blocker object, call its single wake


*


* @throws Exception


*/


private static void Locksupporttest () throws Exception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () throws Exception {


Try Sleep 5s


System.out.println ("Blocker");


Locksupport.park (blocker);


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Locksupporttest";


}


});


T.start (); Start Read thread


Thread.Sleep (150);


Synchronized (blocker) {


Field field = Thread.class.getDeclaredField ("Parkblocker");


Field.setaccessible (TRUE);


Object Fblocker = field.get (t);


System.out.println (blocker = = Fblocker);


Thread.Sleep (100);


System.out.println ("Notifyall");


Blocker.notifyall ();


}


}


/**


* Try to interrupt a object.wait (), throw the corresponding interruptedexception exception


*


* @throws interruptedexception


*/


private static void Interruptwaittest () throws Interruptedexception {


Final Object obj = new Object ();


Thread t = dotest (new Testcallback () {


@Override


public void callback () throws Exception {


Try Sleep 5s


Obj.wait ();


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Interruptwaittest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


T.interrupt (); Check to see if the interrupt is in response to park


}


/**


* Try to interrupt a thread.sleep (), throw the corresponding interruptedexception exception


*


* @throws interruptedexception


*/


private static void Interruptsleeptest () throws Interruptedexception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () throws Exception {


Try Sleep 5s


Thread.Sleep (5000);


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Interruptsleeptest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


T.interrupt (); Check to see if the interrupt is in response to park


}


/**


* Try to interrupt a locksupport.park (), will respond but not throw interruptedexception exception


*


* @throws interruptedexception


*/


private static void Interruptparktest () throws Interruptedexception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () {


Try to park your own thread


Locksupport.parknanos (Blocker, TimeUnit.SECONDS.toNanos (5));


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Interruptparktest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


T.interrupt (); Check to see if the interrupt is in response to park


}


/**


* Try to interrupt a locksupport.unpark (), there will be a response


*


* @throws interruptedexception


*/


private static void Parktest () throws Interruptedexception {


Thread t = dotest (new Testcallback () {


@Override


public void callback () {


Try to park your own thread


Locksupport.park (blocker);


System.out.println ("Wakeup now!");


}


@Override


Public String GetName () {


return "Parktest";


}


});


T.start (); Start Read thread


Thread.Sleep (2000);


Locksupport.unpark (t);


T.interrupt ();


}


public static Thread Dotest (final testcallback call) {


return new Thread () {


@Override


public void Run () {


File File = new file ("/dev/urandom"); Read Linux black Hole


try {


FileInputStream in = new FileInputStream (file);


byte[] bytes = new byte[1024];


while (In.read (bytes, 0, 1024) &gt; 0) {


if (thread.interrupted ()) {


throw new Interruptedexception ("");


}


System.out.println (Bytes[0]);


Thread.Sleep (100);


Long start = System.currenttimemillis ();


Call.callback ();


System.out.println (Call.getname () + "Callback Finish cost:"


+ (System.currenttimemillis ()-start);


}


catch (Exception e) {


E.printstacktrace ();


}


}


};


}


}


Interface Testcallback {


public void callback () throws Exception;


Public String getName ();


}





last


Find the article more and more written longer, then simply sent to the forum, we discussed together. After all, the article describes the use of a level of dongdong, and did not operate from the operating system or sun native to introduce some of the mechanism of thread, familiar with this piece of Daniel's door can also come out to make a comment.
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.