优雅的终止线程
标签:Java并发

终止线程

采用stop方法会使线程立即释放掉锁,这样其他线程可能会获取到半个对象,故我们在终止线程的时候,不能使用 stop方法来。这个实验我们可以采用两种方式来终止线程。

1. 状态标记量

我们可以采用一个 volatile的状态标记量来这是是否要终止线程,这样可以让所有线程保持可见。

public class StopMe implements Runnable{
    volatile boolean stopme=false;
    public void setStopme(){
        stopme=true;
    }

    @Override
    public void run() {
        while (true){
            if (stopme==true){
                System.out.println("exit by stopme");
                break;
            }
            synchronized (StopMe.class){
                System.out.println(Thread.currentThread().getName()+" "+System.currentTimeMillis()/1000);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

测试:

public class Main {

    public static void main(String[] args) throws InterruptedException {
        StopMe stopMe=new StopMe();
        Thread t1=new Thread(stopMe);
        Thread t2=new Thread(stopMe);
        t1.start();
        t2.start();
        Thread.sleep(3000);
        stopMe.setStopme();
    }
}

输出结果为:

Thread-0 1534921060
Thread-1 1534921061
Thread-0 1534921062
exit by stopme
Thread-1 1534921063
exit by stopme

两个线程轮流去执行同步方法,当设置完状态量表示终止时,下一次的两个线程得以停止。

2.中断方式

先复习一下中断方法:

  1. public void Thread.interrupt() 中断线程
  2. public boolean Tread.isInterrupted() 判断是否被中断
  3. public static boolean Thread.interrupted()判断是否被中断,并清除当前中断标志
public class Interrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            while (true){
                if (Thread.currentThread().isInterrupted()){
                    System.out.println("Interrupted");
                    break;
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    System.out.println("Interrupted When Sleep");
                    Thread.currentThread().interrupt();
                }
            }
            Thread.yield();
        });

        thread.start();
        Thread.sleep(1000);
        thread.interrupt();
    }
}

执行结果为:

Interrupted When Sleep
Interrupted

看上面的代码:

Sleep()方法由于中断而抛出异常,此时它会清除中断标记,如果不加处理,那么下一次循环的时候将无法捕获到这个中断,故在异常处理中,再次设置中断标记位。

  • 2 min read

CONTRIBUTORS


  • 2 min read