Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

Thread interrupt in Java is a cooperative mode between threads. The execution of the thread can not be terminated directly by setting the interrupt flag of the thread, but the interrupted thread will handle it according to the interrupt state. That is, “thread interrupt” is not meant literally — the thread actually interrupts, but rather sets the interrupt flag bit to true.

1 thread.interrupt()

This method “interrupts the thread” but only sets the interrupt status bit of the thread to true, depending on the program itself whether the thread dies, waits for a new task, or continues to the next step.

The thread checks this interrupt flag from time to time to determine whether the thread should be interrupted (if the interrupt flag value is true). It does not immediately interrupt a running thread as the stop method does, so there are no problems with stop().

If a thread is blocked (such as by calling thread.sleep, thread.join, thread.wait, condition.await, and I/O operations on interruptible channels), If the thread checks the interrupt flag and finds that the interrupt flag is true, it throws InterruptedException at the point of these blocking method calls and immediately clears the thread’s interrupt flag flag, setting it back to False. The exception is thrown to wake up the thread from its blocked state and give the programmer enough time to process the interrupt request before terminating the thread.

Synchronized blocking cannot be broken during a lock acquisition (the flag bit can be set to true, but no exceptions can be thrown, so it cannot be returned from the blocking state), as well as the lock.lock() method, which is similar to synchronized, which cannot be broken, i.e. if a deadlock occurs, This means that if a deadlock occurs, it is not possible to interrupt a thread that is waiting for a deadlock. But if you call the tryLock method lock.tryLock(long Timeout, TimeUnit Unit) with timeout, it throws an InterruptedException if the thread is interrupted while waiting, which is a very useful feature. Because it allows applications to break deadlocks. You can also call the lock.lockInterruptibly() method, which is equivalent to a tryLock method with timeout set to infinite.

A special case is that threads blocked by locksupport.park () can also be interrupted, but no exception is thrown and flag bits are not restored.

2 thread.isInterrupted()

Use this method if you want to detect whether the current thread is interrupted, because it does not clear the interrupt flag, that is, it does not set the interrupt flag to false, but merely detects the state.

public boolean isInterrupted(a) {return isInterrupted(false); }// ClearInterrupted false Does not reset the flag bit; True Resets the flag bit
private native boolean isInterrupted(boolean ClearInterrupted);

Copy the code

There is another way to check for interruption: Thread.interrupted(), but use this method with caution. This method is called to clear the interrupt flag, that is, reset to false. And this method is a static method of Thread.

public static boolean interrupted(a) {
    return currentThread().isInterrupted(true);
}

Copy the code

Inside interrupted() is the interrupt flag that gets the current calling thread, while isInterrupted() is the interrupt flag that gets the instance object that called the isInterrupted() method.

Verify the following:

public class interrupted {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {}}); thread.start(); thread.interrupt();// Get the interrupt flag, get the child thread interrupt flag
        System.out.println("isInterrupted:" + thread.isInterrupted());
        // Get the interrupt flag and reset, although thread.interrupted(), but actually get the interrupt flag of the main thread because it is called in the main thread
        System.out.println("interrupted:" + thread.interrupted());
        // Get the interrupt flag and reset, also get the main thread interrupt flag
        System.out.println("interrupted:" + Thread.interrupted());
        // Get the interrupt flag, get the child thread interrupt flag
        System.out.println("interrupted:"+ thread.isInterrupted()); }}Copy the code

As a result,

isInterrupted:true
interrupted:false
interrupted:false
interrupted:true
Copy the code

3 application

The sleep, wait, or JOIN () functions are called to block and suspend the current thread while it waits for certain conditions.

For example, if a Thread calls Thread.sleep(3000), the calling Thread is blocked and does not change from blocked to active for 3s. If waiting for 3s is a waste of time, call interrupt() to force the sleep method to throw InterruptedException and restore the thread to its active state.

public class InterruptTest {
    public static void main(String[] args) throws InterruptedException {
        Interrupt interrupt = new Interrupt();
        Thread thread1 = new Thread(interrupt, "thread1");
        Thread thread2 = new Thread(interrupt, "thread2");
        thread1.start();
        // The main thread sleeps for a second, waits for thread1 to acquire the lock, and then opens thread2
        Thread.currentThread().sleep(1000);
        thread2.start();
        // The main thread sleeps again for a second, waiting for Thread2 to become BLOCKED because it cannot acquire the lock.
        Thread.currentThread().sleep(1000);
        // Get the thread2 state
        System.out.println(thread2.getName() + "State." + thread2.getState());
        // Try to set the interrupt state of thread2
        thread2.interrupt();
        Thread2 = thread2, thread2 = thread2, thread2 = thread2
        // But no exception is thrown, so we can't handle the blocked thread
        System.out.println(thread2.getName() + "Is it an interrupted state?" + thread2.isInterrupted());
        System.out.println(thread2.getName() + "Because synchronized blocks, no exception is thrown even in the interrupt state and cannot be ended.");

        System.out.println();
        System.out.println("=========> Start dealing with this problem");
        System.out.println();


        Thread1 is TIMED_WAITING. Thread.sleep(100) can be interrupted and an exception thrown
        System.out.println(thread1.getName() + "State." + thread1.getState());
        // Try to set the interrupt state of thread1
        thread1.interrupt();
        System.out.println(thread1.getName() + "Is it an interrupted state?" + thread1.isInterrupted());

        Thread1 breaks the wait, handles the exception, terminates the run, and releases the lock.
        //thred2 acquires the lock, enters the synchronization block, and executes sleep to enter TIMED_WAITING
        Since thread2 set the interrupt state earlier, it also throws an exception from the sleep method immediately and terminates normally.
    }

    static class Interrupt implements Runnable {
        @Override
        public void run(a) {
            synchronized (Thread.class) {
                try {
                    The wait method can be interrupted, the wait is interrupted, an exception is thrown, and the program can end.
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    // The cache handles the interrupt exception and finishes the wait so that the thread can finish normally
                    System.out.println(Thread.currentThread().getName() + "Exception raised, TIMED_WAITING ended, thread can return");
                }
            }

        }
    }
}

Copy the code

4 Stopping a Thread

The stopping thread here is the ending thread. There are several common methods

  1. When the program ends, the thread ends automatically.
  2. The stop method, however, is outdated and prone to deadlocks.
    1. Immediately stopping all remaining work in the run() method, including ina catch or finally statement (if not ina try block) and throwing a ThreadDeath exception (which normally does not require explicit catch), may result in some clean work not being done, such as closing files, databases, etc.
    2. All locks held by the thread are immediately released. As a result, data cannot be processed synchronously and data inconsistency occurs. If any objects previously protected by these monitors are in an incoherent state, the corrupted objects are visible to other threads, potentially leading to unsafe operations.
  3. Terminates a thread by modifying a variable.
    1. That is, in the thread, define a flag bit, by changing the form of flag bit, end the thread.
  4. thread.interrupt()
    1. The interrupt method can interrupt a thread’s wait state rather than terminate it directly. We can stop part of the waiting thread with an exception thrown
    2. If a thread is calling the wait(), wait(long), or wait(long, int) method of the Object class, Or the join(), join(long), join(long, int), sleep(long) or sleep(long, int) methods of the class are blocked, where the disconnection state will be cleared. It will also receive an InterruptedException — thrown when a thread is in a waiting, sleeping, or occupied state before or during an activity and the thread is interrupted. We can end the thread by catching an exception in a catch and changing the flag bit, or by breaking out of the loop.
    3. If you want to interrupt the wait state of a thread waiting to acquire a lock, this method needs to work with lock.lockInterruptibly() or trylock() to acquire the lock! Because this way of acquiring the lock allows the thread waiting for the lock to be interrupted. If you use the lock() method, the interrupt() method is invalid and a thread that is waiting (blocked) because it cannot acquire the lock cannot be broken, nor can synchronized waits.

If you don’t understand or need to communicate, you can leave a message. In addition, I hope to collect, pay attention to, I will continue to update Java tutorials!