java如何正确停止一个线程

Thread类中有start(), stop()方法,不过stop方法已经被废弃掉。

平时其实也有用过,共享一个变量,相当于标志,不断检查标志,判断是否退出线程

如果有阻塞,需要使用Thread的interrupt()方中断阻塞,线程开始检查标志(PS:抛出异常不会退出循环)

————————————————————我是copy分割线———————————————-

原出处:http://blog.163.com/xh_ding/blog/static/193903289201341685931689

如何停止java的线程一直是一个开发多线程程序常遇到的一个问题。也有好多人问过我,所以今天在这里总结一下希望可以让更多的人知道在java中如何安全的结束一个正在运行的线程。

在Java的多线程编程中,java.lang.Thread类型包含了一些列的方法start(), stop(), stop(Throwable) and suspend(), destroy() and resume()。通过这些方法,我们可以对线程进行方便的操作,但是这些方法中,只有start()方法得到了保留。
在JDK帮助文档以及Sun公司的一篇文章《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中都讲解了舍弃这些方法的原因。
那么,我们究竟应该如何停止线程呢?这里我们介绍两种方法:

  1. 使用共享变量的方式

在这种方式中,之所以引入共享变量,是因为该变量可以被多个执行相同任务的线程用来作为是否中断的信号,通知中断线程的执行。

public class ThreadFlag extends Thread 
{ 
    public volatile boolean exit = false; 

    public void run() 
    { 
        while (!exit); 
    } 
    public static void main(String[] args) throws Exception 
    { 
        ThreadFlag thread = new ThreadFlag(); 
        thread.start(); 
        sleep(3000); // 主线程延迟3秒 
        thread.exit = true;  // 终止线程thread 
        thread.join(); 
        System.out.println("线程退出!"); 
    } 
} 

在上面代码中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false。在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值。

在《Why Are Thread.stop, Thread.suspend,Thread.resume and Runtime.runFinalizersOnExit Deprecated?》中,建议使用如下的方法来停止线程:

 private volatile Thread blinker; 
    public void stop() { 
        blinker = null; 
    } 
    public void run() { 
        Thread thisThread = Thread.currentThread(); 
        while (blinker == thisThread) { 
            try { 
                thisThread.sleep(interval); 
            } catch (InterruptedException e){ 
            } 
            repaint(); 
        } 
    }
  1. 使用interrupt方法终止线程

如果一个线程由于等待某些事件的发生而被阻塞,又该怎样停止该线程呢?这种情况经常会发生,比如当一个线程由于需要等候键盘输入而被阻塞,或者调用Thread.join()方法,或者Thread.sleep()方法,在网络中调用ServerSocket.accept()方法,或者调用了DatagramSocket.receive()方法时,都有可能导致线程阻塞,使线程处于处于不可运行状态时,即使主程序中将该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。这里我们给出的建议是,不要使用stop()方法,而是使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态,退出堵塞代码。

class MyThread extends Thread {
    volatile boolean stop = false;

    public void run() {
        while (!stop) {
            System.out.println(getName() + " is running");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("week up from blcok...");
                stop = true; // 在异常处理代码中修改共享变量的状态
            }
        }
        System.out.println(getName() + " is exiting...");
    }
}
class InterruptThreadDemo3 {
    public static void main(String[] args) throws InterruptedException {
        MyThread m1 = new MyThread();
        System.out.println("Starting thread...");
        m1.start();
        Thread.sleep(3000);
        System.out.println("Interrupt thread...: " + m1.getName());
        m1.stop = true; // 设置共享变量为true
        m1.interrupt(); // 阻塞时退出阻塞状态
        Thread.sleep(3000); // 主线程休眠3秒以便观察线程m1的中断情况
        System.out.println("Stopping application...");
    }
}

注意:在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他线程是否被中断。

<think>好的,我现在需要回答用户关于Java中如何安全停止线程的问题。用户提到了想了解最佳实践,并且系统提示需要引用给定的参考资料。首先,我得先仔细看看用户提供的引用内容。 引用[1]提到应该避免使用已废弃的stop方法,转而使用更安全的优雅终止方法。引用[2]强调了正确停止线程的重要性,指出错误的停止方式可能有风险。引用[3]展示了一个通过中断来停止线程的代码示例,比如实现Runnable接口并处理InterruptedException。引用[4]和[5]可能和线程管理相关,但主要关于ThreadLocal和线程启动,可能暂时用不上。 接下来,我需要整理出停止线程正确方法。根据这些引用,最佳实践应该是使用中断机制。首先,线程应该检查中断状态,或者在阻塞时捕获InterruptedException,然后合理处理。同时,不能使用stop()方法,因为它不安全,会导致资源未释放等问题。 然后,我需要分步骤说明最佳实践。可能需要包括设置中断标志、处理中断异常、以及如何正确响应中断。此外,用户可能想知道具体如何实现,比如代码示例。但根据引用中的例子,比如引用[3]里的RightWayToStopThreadReInterrupt类,可以引用这个作为正确方法。 还要注意是否需要提到其他方法,比如通过标志位控制循环退出,但结合引用内容,主要强调中断机制。此外,需要指出避免使用stop()、suspend()等废弃方法,引用[1]和[2]都提到了这一点。 可能还需要提到线程处于阻塞状态时的处理,比如在捕获InterruptedException后恢复中断状态,确保上层代码能感知到中断。引用[3]的代码示例中可能展示了这一点,通过调用Thread.currentThread().interrupt()来重新设置中断状态。 最后,总结最佳实践,确保结构清晰,分点说明,并引用相应的参考资料。比如,分为检查中断状态、处理中断异常、避免使用废弃方法等几点,每个点后面添加对应的引用标记。 现在需要确保回答符合系统指令:使用中文,行内公式用$...$,独立公式用$$...$$,但这个问题可能不涉及数学公式。引用部分要在相关段落末尾自然添加标识,如[^1]。同时生成相关问题,根据用户的问题,可能涉及中断机制、处理阻塞线程、废弃方法的替代方案等。 在生成相关问题时,要考虑用户可能进一步想了解的内容,比如如何检测中断状态,或者实际应用中的例子。结合引用里的内容,可以问如何正确响应中断,或者ThreadLocal在此场景下的作用(虽然引用[4]主要讲ThreadLocal,但可能不直接相关,但用户可能想知道数据隔离与线程停止的关系,不过可能不太相关,所以可能不放在相关问题里)。 总结回答结构:首先说明最佳实践是使用中断机制,然后分点详细说明每个步骤,包括代码示例,最后总结,并附上相关问题。</think>### Java线程安全停止的最佳实践 在Java中,**安全停止线程的核心是通过协作式中断机制**,而非强制终止。以下是具体实践方法: --- #### 1. **使用中断标志(Interrupt Status)** 线程通过检查自身的中断状态主动退出执行。例如: ```java public class SafeStopThread implements Runnable { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { // 执行任务逻辑 } } } ``` 调用`thread.interrupt()`时,线程会检测到中断状态并终止循环[^1][^3]。 --- #### 2. **正确处理阻塞操作的中断** 当线程处于阻塞状态(如`sleep()`、`wait()`或I/O操作)时,需捕获`InterruptedException`并恢复中断状态: ```java public void run() { try { while (!Thread.currentThread().isInterrupted()) { Thread.sleep(1000); // 阻塞操作 } } catch (InterruptedException e) { // 恢复中断状态,确保上层逻辑能感知 Thread.currentThread().interrupt(); } } ``` 此操作避免因异常处理丢失中断信号[^5]。 --- #### 3. **避免使用废弃方法** - **禁止使用`stop()`**:该方法会强制终止线程,可能导致资源未释放或数据不一致[^1][^2]。 - **避免`suspend()`和`resume()`**:易引发死锁,已被标记为废弃。 --- #### 4. **通过共享变量协作终止(补充方案)** 若需更灵活的控制,可结合自定义标志位: ```java public class Task implements Runnable { private volatile boolean stopped = false; public void stop() { stopped = true; } @Override public void run() { while (!stopped) { // 执行任务逻辑 } } } ``` 需注意**使用`volatile`保证可见性**,或通过原子类(如`AtomicBoolean`)实现[^4]。 --- ### 总结 | 方法 | 适用场景 | 注意事项 | |--------------------|------------------------|-----------------------------| | 中断标志 | 通用协作终止 | 需循环检测中断状态 | | 处理`InterruptedException` | 阻塞操作中 | 恢复中断状态 | | 共享变量 | 需自定义控制逻辑 | 保证可见性/原子性 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值