Mind map link
Multithreading system learning notes link
Refer to the intensive course of Java concurrency core knowledge system on muke.com
Overview of thread interrupts
Common interview questions:
1. How to stop a thread
answer:
-
- Using the interrupt method to request instead of forcibly terminating the thread is a cooperative mechanism.
In this way, the thread requested to interrupt can independently decide to process its own logic.
The advantage of this is that it can ensure data security, clean up in time and ensure data integrity.
-
-
If the interrupt method works, it needs to be used in many ways
1 is the interrupt request sent by the requesting party
2. The stopped party shall check the interrupt signal in each cycle or at an appropriate time,
And process this signal when an InterruptException may be thrown
3. If the thread is stopped by a sub method and the sub method is called, there are two best practices
1) To pass an interrupt, i.e. give priority to throwing an exception upward at the sub method layer, pass the interrupt signal to the run method, and process the interrupt signal logic at the run method layer
2) Resume interrupt, that is, after receiving the interrupt signal, the sub method sets the interrupt state again.
-
-
-
If interrupt is not used, other methods will have certain disadvantages and consequences
1) Stop will suddenly stop the thread. If the thread has no time to process the remaining data, the data will be incomplete
2) Suspend and other methods will suspend the thread, not destroy the object, hold the lock and block, which will lead to deadlock
3) Setting the boolean flag bit with volatile cannot handle long-term blocking, resulting in the thread being unable to stop
-
Relevant code certificate
There are two best practices for sub methods:
- Delivery interruption:
package threadcoreknowledge.stopthreads; import threadcoreknowledge.createthreads.ThreadStyle; /** * Description: Best Practices 1: * catch Preferences after interruptiedexcetion: * If an exception is thrown in the method signature, try/catch will be forced in run() */ public class RightWayStopThreadInProd implements Runnable { @Override public void run() { while (true && !Thread.currentThread().isInterrupted()) { System.out.println("go"); try { throwInMethod(); } catch (InterruptedException e) { // The run method handles exception logic Thread.currentThread().interrupt(); //Save log, stop program System.out.println("Save log"); e.printStackTrace(); } } } private void throwInMethod() throws InterruptedException { // Subprocess throw up exception Thread.sleep(2000); } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new RightWayStopThreadInProd()); thread.start(); Thread.sleep(1000); thread.interrupt(); } }
- Recovery interruption:
package threadcoreknowledge.stopthreads; /** * Description: Best Practices 2: * Calling Thread. in the catch subclause currentThread(). Interrupt() to restore the set interrupt state, * So that the interruption just occurred can still be checked in the subsequent implementation * Go back to the RightWayStopThreadInProd just now, fill in the interrupt and let it jump out */ public class RightWayStopThreadInProd2 implements Runnable { @Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { // Detection interrupt System.out.println("Interrupted,End of program operation"); break; } reInterrupt(); } } private void reInterrupt() { try { Thread.sleep(2000); // The interrupt flag is cleared and becomes false } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Interrupt again and set the flag bit to true e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new RightWayStopThreadInProd2()); thread.start(); Thread.sleep(1000); thread.interrupt(); } }
Setting the boolean flag bit with volatile cannot handle long-term blocking
package threadcoreknowledge.stopthreads.volatiledemo; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; /** * Description: demonstrates that volatile cannot stop a thread when its limited part2 is blocked * In this example, the production speed of producers is fast and the consumption speed of consumers is slow, * Therefore, when the blocking queue is full, producers will block and wait for consumers to consume further */ public class WrongWayVolatileCantStop { public static void main(String[] args) throws InterruptedException { // Define blocking queue ArrayBlockingQueue storage = new ArrayBlockingQueue(10); // Producer startup Producer producer = new Producer(storage); Thread producerThread = new Thread(producer); producerThread.start(); Thread.sleep(1000); // Consumer startup Consumer consumer = new Consumer(storage); while (consumer.needMoreNums()) { // Normal consumption of consumers System.out.println(consumer.storage.take()+"Consumed"); Thread.sleep(100); } // Consumers stop spending System.out.println("Consumers don't need more data."); //Once consumption does not need more data, we should stop producers, but the actual situation does not work producer.canceled=true; System.out.println(producer.canceled); // true } } // Producer logic class Producer implements Runnable { public volatile boolean canceled = false; // Define flag bit BlockingQueue storage; // Blocking queue public Producer(BlockingQueue storage) { this.storage = storage; } @Override public void run() { int num = 0; try { while (num <= 100000 && !canceled) { // Flag bit cannot be blocked queue response if (num % 100 == 0) { storage.put(num); // Adding elements to the blocking queue will respond to exceptions if interrupted System.out.println(num + "Is a multiple of 100,Put it in the warehouse."); } num++; } } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("Producer end run"); } } } // Consumer logic class Consumer { BlockingQueue storage; public Consumer(BlockingQueue storage) { this.storage = storage; } // Set a random proportion so that consumers don't consume public boolean needMoreNums() { if (Math.random() > 0.95) { return false; } return true; } }
- Repair scheme
... // Interrupt with interrupt producerThread.interrupt(); } class Producer implements Runnable { BlockingQueue storage; public Producer(BlockingQueue storage) { this.storage = storage; } @Override public void run() { int num = 0; try { while (num <= 100000 && !Thread.currentThread().isInterrupted()) { // Interrupt detection if (num % 100 == 0) { storage.put(num); // Will respond to Interrupt signal System.out.println(num + "Is a multiple of 100,Put it in the warehouse."); } num++; } ...
2. How to handle non interruptible blocking
answer:
-
- Unfortunately, there is no universal solution,
- Different solutions should be given for some locks or some IO S
- For example, for reentrantlock (reentrant lock), if the lock method is used and blocked during the lock process, there is no way to respond to the interrupt response, but this class provides the lockInterrupt method, which can respond to the interrupt response
- That is, according to the characteristic situation, use the characteristic method to make them respond to the interrupt