这篇文章再来讲一些JAVA多线程中不常用,但是实际上又很重要的一些小方法,如果对多线程的其他知识有兴趣,可以翻看我的其他文章,兴许能够对您的多线程的学习添砖加瓦~

再说interrupt()方法前,我想给大家介绍一下线程的结束的原理帮助大家来深刻的理解一下interrupt()方法的出现

中断结束的原理

我们理论上只需要让run()停止运行,那么线程就结束了

我看了网上很多其他大佬写的帖子,基本上一上来就给大家写一个while()或者for()循环,然后在里面写interrup()来停止

事实上确实是,我写的帖子主要是针对初学者,我相信大佬也不需要看我的帖子了

我随意从网上赋值一下大佬写的示例代码(如有冒犯,实属抱歉,只是为了把原因说清楚):

public class ThreadTest implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new ThreadTest());
thread.start();
Thread.sleep(500);
thread.interrupt();
}
@Override
public void run() {
while (true) {
try {
System.out.println("try:"+Thread.currentThread().isInterrupted());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("catch:"+Thread.currentThread().isInterrupted());
}
}
}
}

网上大部分大佬的帖子都是类似的,用了一个循环然后来打断循环,为什么要使用循环,原因也很简单

线程的提出主要就是针对循环等费时间的程序,如果是顺序执行代码,单线程完全可以自己实现,没有什么必要写多线程

只要原因了,我也会在下面的示例代码中用循环操作

既然是循环操作,那么是不是意味着我们如果能够把线程中的循环等费时操作给打断,那么线程不就可以很快结束了吗?顺寻执行代码速度很快,大家没意见吧。

在没有引入interrupt()的情况下,我们来打断线程

/*
需求:通过改变标记来停止线程的运行
*/
public class interruptDemo implements Runnable{
private boolean flag=true;
public void run() {
int count=0;
while(flag)
{
System.out.println("I am run!"+count++);
}
System.out.println("over");
}
void setflag(boolean flag) {
this.flag=flag;
}
}
import java.util.LinkedList;
public class TestDemo {
public static void main(String[] args) {
interruptDemo in=new interruptDemo();
Thread t=new Thread(in);
t.start();
for(int i=0;i<100;i++)
{
System.out.println("I am main"+i);
}
in.setflag(false);
}
}

大家可以试试,运行会很完美,线程执行一半就会停止下来,我们已经成功的通过改变标记来停止线程了

wait()等方法剥夺CPU

当然其实并不是所有的线程都可以这样子停止

比如说这样

/*
需求:通过改变标记来停止线程的运行
*/
public class interruptDemo implements Runnable{
private boolean flag=true;
public void run() {
function();
}
synchronized void function()
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int count=0;
while(flag)
{
System.out.println("I am run!"+count++);
}
System.out.println("over");
}
void setflag(boolean flag) {
this.flag=flag;
}
}

这里把子线程的打印单独拎出来了,然后再加了this锁,保证每次只有一个线程进行访问,里面加了wait()方法,运行到了wait()就会挂起,被剥夺了执行权限

很显然这种情况下,我们没办法把子线程停止,它会一直挂起

本质原因在于子线程被剥夺了执行资格(CPU),没办法继续执行

所以我们的办法就是我们要让它再次恢复资格

这才是真正为什么要引出interrupt()的根本原因

interrupt()

对于线程的执行,大家都很清楚最基本的三个状态:就绪、运行、结束,分别对应的方法是start()、run()、stop()

但是很遗憾由于stop()存在一些安全问题,已经过时弃用了,那么我们需要找出一种合适的方法来代替stop()

interrupt()的功能就是让线程再次获得执行权限,打断wait、join()、sleep()等方法

最终的代码会是这样子

/*
需求:通过改变标记来停止线程的运行
*/
public class interruptDemo implements Runnable{
private boolean flag=true;
public void run() {
function();
}
synchronized void function()
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("我被打断了");//wait()打断后会抛出异常
}
int count=0;
while(flag)
{
System.out.println("I am run!"+count++);
}
System.out.println("over");
}
void setflag(boolean flag) {
this.flag=flag;
}
}
public class TestDemo {
public static void main(String[] args) {
interruptDemo in=new interruptDemo();
Thread t=new Thread(in);
t.start();
for(int i=0;i<100;i++)
{
System.out.println("I am main"+i);
}
in.setflag(false);
t.interrupt();//打断挂起,让子线程再次获得执行权限
}
}

这里通过interrupt打断线程的沉睡

网上很多都提到了isinterrupted,这个仅仅是一种标记而已,和flag类似,但是它在抛出后又恢复原来的值

那么使用interrupted就是这样的

/*
需求:通过改变标记来停止线程的运行
*/
public class interruptDemo implements Runnable{
private boolean flag=true;
public void run() {
function();
}
synchronized void function()
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("我被打断了");//wait()打断后会抛出异常
}
int count=0;
System.out.println(Thread.interrupted());
while(Thread.interrupted())
{
System.out.println("I am run!"+count++);
}
System.out.println(Thread.interrupted());
System.out.println("over");
}
void setflag(boolean flag) {
this.flag=flag;
}
}
public class TestDemo {
public static void main(String[] args) {
interruptDemo in=new interruptDemo();
Thread t=new Thread(in);
t.start();
for(int i=0;i<100;i++)
{
System.out.println("I am main"+i);
}
in.setflag(false);
t.interrupt();//打断挂起,让子线程再次获得执行权限
}
}

总结

stop()由于存在安全问题已经弃用

多线程是用来解决某些耗时操作,我们可以通过打断耗时操作来结束线程

interrupt()并不是真正的让线程停下来,它其实只是改变了一下执行标记,最终还是需要我们来完成线程的停止

isinterruped就是一种内部标记和interrupt()配合使用

wait、join()、sleep()剥夺执行权限之后,interrupt可以中断这种挂起