当前位置:网站首页>Concurrent programming - how to interrupt / stop a running thread?

Concurrent programming - how to interrupt / stop a running thread?

2022-07-05 07:04:00 Handling Gong

How to interrupt or stop a running thread correctly ? This is a very classic interview question , It covers a lot of knowledge points , After reading this article , Take you to thoroughly master the correct interruption 、 Methods to stop threads .

  What is interrupt mechanism ?

First

A thread should not be forced to interrupt or stop by other threads , It is The thread should stop itself , Decide your own destiny .

therefore ,Thread.stop,Thread.suspend,Thread.resume It's been abandoned .

secondly
stay Java There is no way to stop a thread immediately , However, stopping threads is particularly important , For example, cancel a time-consuming operation . therefore ,Java Provides a negotiation mechanism for stopping threads -- interrupt , That is, interrupt identification negotiation mechanism .

Interruption is just a collaborative negotiation mechanism ,Java No syntax added to interrupt , The interruption process needs to be implemented by the programmer himself .
To interrupt a thread , You need to manually call the thread's interrupt Method , This method only sets the interrupt ID of the thread object to true;
Then you need to write your own code to constantly detect the identification bit of the current thread , If true, Indicates that another thread requests this thread to interrupt .

What to do at this time requires you to write your own code to realize .

Each thread object has an interrupt identifier bit , Used to indicate whether a thread is interrupted , The identification bit is true To interrupt , by false Means not interrupted ;

By calling the interrupt Method to set the identification bit of the thread to true; Can be invoked in other threads , You can also call it in your own thread .

Threads (Thread class ) Interrupted API Method

Since there is a business scenario of thread interruption , that Java The Bulls must also have thought of , And the corresponding API Method to accomplish , Let's take a look at what they have , How are they realized .

void interrupt()

Example method , Just set the interrupt status of the thread to true, Initiate a negotiation without immediately stopping the thread .

static boolean interrupted()

Static methods ,Thread.interrupted();

Determine whether the thread is interrupted and clear the current interrupt state .

This method does two things :

1. Returns the interrupt status of the current thread , Tests whether the current thread has been interrupted

2. Clear the interrupt state of the current thread and reset it to false, Clear the interrupt state of the thread

This method is a little difficult to understand , If you call this method twice in a row , The second call will return false, Because the results of two consecutive calls may be different

boolean isInterrupted()

Example method

Determine whether the current thread is interrupted ( Check the interrupt flag bit )

  How to stop interrupting a running thread ?

1. adopt volatile Set shared variables

public class InterruptedDemo {

	/**
	*  Thread interrupt flag bit 
	*/
	static volatile boolean stopFlag = false;

	public static void main(String[] args) {
		new Thread(() -> {
			while (true) {
				if (stopFlag) {
					System.out.println(Thread.currentThread().getName() + "  Thread the interrupt , Stop running !");
					break;
				}
				System.out.println(Thread.currentThread().getName() + "  Thread start , Start moving bricks ...");
			}

		},"t1").start();

		try { TimeUnit.MILLISECONDS.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); }
		//  The main thread tells t1  Threads , Need to interrupt 
		stopFlag = true;
	}
}

2. AtomicBoolean Atomic classes

static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
public static void main(String[] args) {
	new Thread(() -> {
		while (true) {
			if (atomicBoolean.get()) {
				System.out.println(Thread.currentThread().getName() + "  Thread the interrupt , Stop running !");
				break;
			}
			System.out.println(Thread.currentThread().getName() + "  Thread start , Start moving bricks ...");
		}
	},"t1").start();
	try { TimeUnit.MILLISECONDS.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); }
	//  The main thread tells t1  Threads , Need to interrupt 
	atomicBoolean.set(true);

This and the above volatile equally , The same thing can be done .

3. Thread API

public static void main(String[] args) {
	Thread t1 = new Thread(() -> {
		while (true) {
			if (Thread.currentThread().isInterrupted()) {
				System.out.println(Thread.currentThread().getName() + "  Thread the interrupt , Stop running !");
				break;
			}
			System.out.println(Thread.currentThread().getName() + "  Thread start , Start moving bricks ...");
		}
	},"t1");
	t1.start();
	try { TimeUnit.MILLISECONDS.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); }
	// t2 Thread notification  t1  Thread interrupt 
	new Thread(() -> t1.interrupt(),"t2").start();
}

4. interrupt()、isInterrupted() Source code analysis

  Called the underlying native Method interrupt0(), Just set a sign .

Reset flag bit to false.

By looking at the source code , The conclusion is as follows :

When it comes to a thread , call interrupt() when :
① If the thread is in Normal active state , The thread's interrupt flag will be set to true, That's it .

The thread with interrupt flag will continue to run normally , Unaffected .
therefore ,interrupt() It doesn't really interrupt threads , You need to cooperate with the called thread .

② If the thread is blocked ( For example, in the sleep、wait、join Equal state ), To call the current thread object in another thread interrupt Method , Then the thread will immediately exit the blocked state , And throw a InterruptedException abnormal .

Here's a simple case Let's demonstrate the conclusion :

  • Verify that the interrupt command is issued to the thread interrupt after , The interrupt will not be executed immediately
public static void main(String[] args) {
	Thread t1 = new Thread(() -> {
		for (int i = 0; i < 200; i++) {
			System.out.println("----> " + i);
		}
		//  here , verification  t1  Whether the thread receives the interrupt request , The execution of the output here is terminated immediately ?
		System.out.println("t1 Interrupt flag bit of thread 02 --> " + Thread.currentThread().isInterrupted()); // true
	},"t1");
	t1.start();
	System.out.println("t1 The default interrupt flag bit of the thread --> " + t1.isInterrupted()); // false
	try { TimeUnit.MILLISECONDS.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); }
	//  Send thread interrupt request 
	t1.interrupt();
	System.out.println("t1 Interrupt flag bit of thread 01 --> " + t1.isInterrupted()); // true
	try { TimeUnit.MILLISECONDS.sleep(500L); } catch (InterruptedException e) { e.printStackTrace(); }
	//  here ,t1  Thread has ended , Return to the default state 
	System.out.println("t1 Interrupt flag bit of thread 03 --> " + t1.isInterrupted()); // false
}

 

 t1 After thread execution , Get the interrupt identification bit of the thread for the second time through the output of the console , Also time true.

When our main thread sleeps 500 ms after ,t1 The thread has finished executing , End of life cycle , At this time, the third acquisition t1 Interrupt identification bit of thread , It's changed into false. It verifies our conclusion : For inactive threads , Interrupt request defaults to false.

  • Verify that it is blocked , Calling the interrupt method throws an exception
public static void main(String[] args) {
	Thread t1 = new Thread(() -> {
		while (true) {
			if (Thread.currentThread().isInterrupted()) {
				System.out.println(Thread.currentThread().getName() + "  Thread the interrupt !!");
				break;
			}
			System.out.println("----> validate InterruptedException..");
			try {
				TimeUnit.MILLISECONDS.sleep(200);
			} catch (InterruptedException e) {
				//  After throwing an exception , The interrupt ID of the thread will be cleared , Reset to default ,
				//  therefore , If you don't add this line of code , There will be an endless cycle , Other thread pairs  t1  The interrupt request sent by the thread failed 
				Thread.currentThread().interrupt();
				e.printStackTrace();
			}
		}
	}, "t1");
	t1.start();
	try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); }
	//  Send thread interrupt request 
	t1.interrupt();
}

  •  static boolean interrupted() Static method description
public static void main(String[] args) {
	System.out.println(Thread.currentThread().getName() + "  Thread interrupt status 01 ----> " + Thread.currentThread().isInterrupted());
	/**
	 * Thread.interrupted()   Static methods , Did two things 
	 * 1.  Returns the interrupt status of the current thread , Tests whether the current thread has been interrupted 
	 * 2. Clear the interrupt state of the current thread and reset it to  false, Clear the interrupt state of the thread 
	 */
	Thread.currentThread().interrupt();
	System.out.println("======  Send interrupt request  =======");
	System.out.println(Thread.currentThread().getName() + "  Thread interrupt status 02 ----> " + Thread.currentThread().isInterrupted());
	System.out.println(Thread.currentThread().getName() + "  Thread interrupt status 03 ----> " + Thread.interrupted());
	System.out.println(Thread.currentThread().getName() + "  Thread interrupt status 04 ----> " + Thread.currentThread().isInterrupted());
}

  Take a look at the source code :

  It can be seen that , Static method and instance method , In fact, they all call the same native Method , But the parameters passed in are different , One is to reset the state , One is not needed .

I believe through the above content , Children's shoes have a deeper understanding of interrupt threads !

原网站

版权声明
本文为[Handling Gong]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207050639413944.html