编程语言
首页 > 编程语言> > 重学Java之线程的中断

重学Java之线程的中断

作者:互联网

开启线程都知道了,怎么中断一个线程呢?

这里的中断也叫终止、停止,意思都是停止一个正在运行的线程。

1.设置中断标志位

在线程的执行逻辑中添加标志位判断,

需要中断线程时,修改该标志位,让线程执行逻辑结束。

public class StopThreadTest {

    public static void main(String[] args) throws InterruptedException {

        FThread fThread = new FThread();
        fThread.start();
        Thread.sleep(3000);
        fThread.setFlag(true);
    }
}
class FThread extends Thread{

    private boolean flag_stop = false;

    @Override
    public void run() {
        super.run();
        for (int t = 0; t < 10000; t++){
            if (flag_stop) {
                break;
            }
            System.out.println("FThread[" + Thread.currentThread().getName() + "] working , t = " + t);
            
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // real function
            
        }
        System.out.println("FThread[" + Thread.currentThread().getName() + "] finish");
    }

    public void setFlag(boolean flag){ this.flag_stop = flag; }
}

2.使用 interrupt 方法

在线程的执行逻辑中添加对中断的判断,判断方法是 isInterrupted()

需要中断某个线程时,调用 interrupt 方法。

interrupt 方法的 API 说明:

Interrupts this thread.
Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.
If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread’s interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException.
If this thread is blocked in a java.nio.channels.Selector then the thread’s interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector’s wakeup method were invoked.
If none of the previous conditions hold then this thread’s interrupt status will be set.
Interrupting a thread that is not alive need not have any effect.
Throws:
SecurityException – if the current thread cannot modify this thread

概括:

2.1 直接调用

直接用试试,

public class StopThreadTest {

    public static void main(String[] args) throws InterruptedException {

        CalculateThread thread1 = new CalculateThread("thread1");
        thread1.start();
        thread1.interrupt();
    }
}

class CalculateThread extends Thread{

    private String name;

    public CalculateThread(String name) {
        super(name);
        this.name = name;
    }

    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 10000 ; i++){
            if (this.isInterrupted()) {
                System.out.println("Thread[" + name + "] isInterrupted, exit");
                break;
            }

            System.out.println("Thread[" + name + "] is running, i = " + i);
        }

        System.out.println("Thread[" + name + "] finish");
    }
}

运行结果,

Thread[thread1] isInterrupted, exit
Thread[thread1] finish

一开始就中断,太快了,没看清,加个延时试试。

2.2 带 sleep() 的调用

假设线程中有用 sleep() 方法,看看有什么不一样

public class StopThreadTest {

    public static void main(String[] args) throws InterruptedException {

        CalculateThread thread1 = new CalculateThread("thread1");
        thread1.start();
        Thread.sleep(2000);
        thread1.interrupt();
    }
}


class CalculateThread extends Thread{

    private String name;

    public CalculateThread(String name) {
        super(name);
        this.name = name;
    }

    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 10000 ; i++){
            if (this.isInterrupted()) {
                System.out.println("Thread[" + name + "] isInterrupted, exit");
                break;
            }

            System.out.println("Thread[" + name + "] is running, i = " + i);

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.out.println("InterruptedException");
                e.printStackTrace();
            }
        }

        System.out.println("Thread[" + name + "] finish");
    }
}

运行结果,

Thread[thread1] is running, i = 0
InterruptedException
Thread[thread1] is running, i = 1
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.lah.thread.CalculateThread.run(StopThreadTest.java:68)
Thread[thread1] is running, i = 2
Thread[thread1] is running, i = 3
Thread[thread1] is running, i = 4
Thread[thread1] is running, i = 5
Thread[thread1] is running, i = 6
//后面的继续执行,没成功,省略了

在 sleep() 时被中断,发生了 InterruptedException 异常,和 API 中说明的一样。

解决办法:做好异常处理逻辑

本例,直接在异常时 break 退出即可,

class CalculateThread extends Thread{

    private String name;

    public CalculateThread(String name) {
        super(name);
        this.name = name;
    }

    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 10000 ; i++){
            if (this.isInterrupted()) {
                System.out.println("Thread[" + name + "] isInterrupted, exit");
                break;
            }

            System.out.println("Thread[" + name + "] is running, i = " + i);

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.out.println("InterruptedException");
                e.printStackTrace();
                break; // 这里
            }
        }

        System.out.println("Thread[" + name + "] finish");
    }
}

再次运行就可以中断线程了,

Thread[thread1] is running, i = 0
Thread[thread1] is running, i = 1
InterruptedException
Thread[thread1] finish
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.lah.thread.CalculateThread.run(StopThreadTest.java:68)

3.使用 stop 方法(不推荐)

线程的 stop() 方法是弃用的 API ,不推荐使用。

标签:重学,Java,name,Thread,thread,线程,thread1,sleep
来源: https://blog.csdn.net/weixin_44021334/article/details/119357397