• Java: Java终止线程的几种方式


    首先说明,使用stop方法终止的方式已经在很久之前就被废弃了,在加锁的情况下有可能会造成死锁,这里不做讨论。

    1. 使用标志位终止线程

    在run()方法执行完毕后,该线程就终止了。但是在某些特殊的情况下,希望run()方法中的代码一直循环执行。比如在服务端程序中可能会使用 while(true) { ... } 这样的循环结构来不断的接收来自客户端的请求。此时就可以用修改标志位的方式来结束 run() 方法。例:

    public class ServerThread extends Thread {
        //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
        public volatile boolean exit = false; 
    
        @Override
        public void run() {
            ServerSocket serverSocket = new ServerSocket(8080);
            while(!exit){
                serverSocket.accept(); //阻塞等待客户端消息
                ...
            }
        }
        
        public static void main(String[] args) {
            ServerThread t = new ServerThread();
            t.start();
            ...
            t.exit = true; //修改标志位,退出线程
        }
    }

    Note:一定要给标志位加上volatle 关键字!详细原因可参考:https://www.cnblogs.com/yongdaimi/p/9566332.html 或者 https://www.cnblogs.com/dolphin0520/p/3920373.html 。 

    2. 使用interrupt()方法来终止线程

    interrupt()方法用于中断线程,调用该方法的线程状态将会被置为“中断状态”。
    Note: 线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。java中的那些支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。

    调用这种方式去终止的线程存在两种情况:

    第一种情况:该线程循环执行不会存在阻塞
    比如,在while 循环中循环打印一句话:这样的话调用interrupt()会立即终止该线程。例:

    package com.yongdaimi.java.demo;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test3 {
        
        
        public static void main(String[] args) {
            NotInterruptThread mNotInterruptThread = new NotInterruptThread();
            mNotInterruptThread.start();
            
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            mNotInterruptThread.interrupt();
        }
    
        
        static class NotInterruptThread extends Thread {
            @Override
            public void run() {
                super.run();
                while (!isInterrupted()) {
                    System.out.println("=============NotInterruptThread execute... =============");
                }
            }
            
        }
        
    }

    运行结果:

    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    =============NotInterruptThread execute... =============
    5 秒后,打印就会停止。

    第二种情况:该线程循环执行存在阻塞状态
    比如,在线程中存在sleep()、await()、wait(long) 这种能够抛出:interruptedException 异常的方法,这种情况调用interrupt()方法后将会触发这些异常,可以选择在触发异常后调用break来终止线程。例:

    package com.yongdaimi.java.demo;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test3 {
        
        
        private static Object sLock = new Object();
        
    
        private static ReentrantLock sReentrantLock = new ReentrantLock();
        private static Condition sSuspendCondition = sReentrantLock.newCondition();
        
        public static void main(String[] args) {
            /*NotInterruptThread mNotInterruptThread = new NotInterruptThread();
            mNotInterruptThread.start();
            
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            mNotInterruptThread.interrupt();
            */
            
            
            InterruptThread interruptThread = new InterruptThread();
            interruptThread.start();
            
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            interruptThread.interrupt();
            
            
            /*InterruptThread1 interruptThread1 = new InterruptThread1();
            interruptThread1.start();
            
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            interruptThread1.interrupt();*/
            
            /*InterruptThread2 interruptThread2 = new InterruptThread2();
            interruptThread2.start();
            
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            
            interruptThread2.interrupt();*/
            
            /*sReentrantLock.lock();
            try {
                sSuspendCondition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                sReentrantLock.unlock();
            }*/
            
            
        }
    
        
        
    
        static class NotInterruptThread extends Thread {
            @Override
            public void run() {
                super.run();
                while (!isInterrupted()) {
                    System.out.println("=============NotInterruptThread execute... =============");
                }
            }
            
        }
        
        
        static class InterruptThread extends Thread {
    
            @Override
            public void run() {
                super.run();
                while (!isInterrupted()) {
                    System.out.println("=============InterruptThread execute... =============");
                    try {
                        Thread.sleep(50000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        }
        
        
        static class InterruptThread1 extends Thread {
    
            @Override
            public void run() {
                super.run();
                while (!isInterrupted()) {
                    synchronized (sLock) {
                        System.out.println("=============InterruptThread execute... =============");
                        try {
                            sLock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            break;
                        }
                    }
                }
            }
        }
        
    
        
        static class InterruptThread2 extends Thread {
    
            @Override
            public void run() {
                super.run();
                while (!isInterrupted()) {
                    sReentrantLock.lock();
                    try {
                        System.out.println("=============InterruptThread execute... =============");
                        sSuspendCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    } finally {
                        sReentrantLock.unlock();
                    }
                }
            }
        }
        
        
    }

    我这里分别演示了使用sleep()、wait()、await()的方式来阻塞线程,然后在主线程休眠一段时间后尝试去中断,子线程中收到异常后调用break退出循环,实际试验都可以正常退出循环。

    参考链接:

    1. interrupt、interrupted 、isInterrupted 区别

    2. Java终止线程的三种方法

  • 相关阅读:
    团队冲刺——第六天
    团队冲刺——第五天
    用户场景分析和第一阶个人计划。
    Java-web 学习感触一界面传值
    Java-web 学习感触一知识储备
    基于”Layui"框架构建前端页面
    HNC公司销售合同管理系统开发反思
    第十六周总结
    个人课程总结
    第十五周总结
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/12074507.html
Copyright © 2020-2023  润新知