文档章节

多线程学习(四)

scymore
 scymore
发布于 2016/08/29 17:29
字数 1321
阅读 12
收藏 0

在Java中有三种方法用于停止线程:

    1 . 使用退出标识,使线程正常退出, 也就是当run()方法完成后终止线程.

    2 . 使用stop()方法强制停止线程, 但是不推荐这种方法, 因为stop和suspend , resume方法一样, 都是作废过期的方法, 使用这类似的方法可能导致不可预期的错误.

    3 . 使用interrupt方法终止线程.

 

一 . interrupt()

    下述代码将使用interrupt()方法进行停止线程,但是interrupt()方法的使用效果并不像for循环中的break一样,马上就停止循环. 调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真正的停止线程.所以在使用interrupt()方法的时候还需要加入一个判断才可以完成线程的停止.

    

    代码段:

public class MyThread extends Thread {
    
        @Override
        public void run() {
            super.run();
            for (int i = 0; i < 500000; i++) {
                System.out.println("i = " + (i + 1));
            }
        }
    
    }

    运行类:

public class Test {
        public static void main(String[] args) {
            try{
                MyThread myThread = new MyThread();
                Thread thread = new Thread(myThread);
                thread.start();
                Thread.sleep(1000);
                thread.interrupt();
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    }

运行结果:

    

    从运行结果可以看出,interrupt()方法并没有将当前线程停止.

二 . 判断线程是否停止

        Java中Thread.java类中提供了两种方法进行判断线程是否停止的判断

        1 . interrupted()

             测试当前线程是否已经中断(会清除线程中断状态)

             测试当前线程是否是中断状态,执行后具有将状态标识清除为false的功能.

        2 . isInterrupted()

             测试线程Thread对象是否已经是中断状态,但不提供清除状态标识为false的功能.

 

三 . 停止线程(异常停止)

public class MyThread extends Thread {

            @Override
            public void run() {
                super.run();
                for (int i = 0; i < 500000; i++) {
                    if (this.interrupted()) {
                        System.out.println("Thread interrupted.");
                        break;
                    }
                    System.out.println("i = " + (i + 1));
                }
                System.out.println("end.");
            }

        }
public class Test {
            public static void main(String[] args) {
                try {
                    MyThread myThread = new MyThread();
                    myThread.start();
                    myThread.setName("test");
                    Thread.sleep(1000);
                    myThread.interrupt();
                    System.out.println("线程名字 :" + myThread.getName());
                    System.out.println("线程是否中断 : " + myThread.interrupted());
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

    运行结果:

使用这种方法将线程停止后for循环后面的代码还会继续运行, 如果for循环后面还存在一个或多个for循环,则该线程并不会结束.

 

所以,将第一段代码进行修改:

public class MyThread extends Thread {

    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 500000; i++) {
                if (this.interrupted()) {
                    System.out.println("Thread interrupted.");
                    throw new InterruptedException();
                }
                System.out.println("i = " + (i + 1));
            }
            System.out.println("end.");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

    运行结果:

    

由两次运行结果可以看出for循环后面的end没有输出.

 

四 . 停止线程(睡眠停止)

       先停止,在进入sleep

public class MyThread extends Thread {

    @Override
    public void run() {
        super.run();
        try {
            for(int i = 0 ; i < 100000 ; i ++){
                System.out.println(" i = " + (i + 1));
            }
            System.out.println("Thread run begin");
            Thread.sleep(200000);
            System.out.println("Thread run end");
        }catch (Exception e){
            System.out.println("end in sleep ." + this.interrupted());
            e.printStackTrace();
        }
    }

}
public class Test {
    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            myThread.setName("test");
            myThread.interrupt();
            System.out.println("线程名字 :" + myThread.getName());
            System.out.println("线程是否中断 : " + myThread.interrupted());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

运行结果:

注:如果先进入sleep,在停止线程,会进入catch语句,并且清除状态值,使之变为false.

     先停止在进入sleep,也会进入catch,但是不会清除状态值.

五 . 暴力停止

      暴力停止即直接使用stop()方法    

public class MyThread extends Thread {

            private int i = 0 ;
            @Override
            public void run() {
                super.run();
                try {
                    while(true){
                        i ++;
                        System.out.println(" i = " + i );
                        Thread.sleep(1000);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

        }

        

public class Test {
            public static void main(String[] args) {
                try {
                    MyThread myThread = new MyThread();
                    myThread.start();
                    myThread.setName("test");
                    Thread.sleep(8000);
                    myThread.stop();
                    System.out.println("线程名字 :" + myThread.getName());
                    System.out.println("线程是否中断 : " + myThread.interrupted());
                } catch (Exception e) {
                    e.printStackTrace();
                }
        
            }
        }

    运行结果:

    

 

        注 : 方法stop和java.lang.ThreadDeath异常

              在调用stop()方法时,会抛出java.lang.ThreadDeath异常,但是一般情况下不需要特意去捕获该异常 

              方法stop()已经作废了,因为如果强制让线程停止则有可能使一些清理性的工作无法完成,另外一种情况就是对锁定的对象进行了解锁,导致数据得不到同步的处理,出现数据不一致的问题.

 

六 .  释放锁的不良影响

        使用stop()方法停止线程释放锁以后会给数据造成不一致的结果,如果出现这样的情况,程序处理的数据就有可能遭到破坏,最终导致程序执行的流程出错.

public class Start {
    private String a = "a";
    private String b = "b";

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    synchronized public void printString(String username , String pswd){
        try{
            a = username;
            Thread.sleep(1000);
            b = pswd;
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

 

public class MyThread extends Thread {

    private Start start;

    public MyThread(Start startObject){
        super();
        start = startObject;
    }

    @Override
    public void run(){
        start.printString("b","bb");
    }
}
public class Test {
    public static void main(String[] args) {
        try {
            Start start = new Start();
            MyThread myThread = new MyThread(start);
            myThread.start();
            Thread.sleep(500);
            myThread.stop();
            System.out.println("name = " + start.getA() + " ; password = " + start.getB());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

运行结果:

    

由于stop()方法已经在JDK中呗标记为作废的方法,所以他在功能上具有缺陷,尽量不要在程序中使用.

 

七 .  使用return停止线程

        将方法interrupt()和return结合使线程停止.

public class MyThread extends Thread {

    @Override
    public void run(){
        while(true){
            if(this.isInterrupted()){
                System.out.println("Thread ended.");
                return;
            }
            System.out.println("time = " + System.currentTimeMillis());
        }
    }
}
public class Test {
    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            Thread.sleep(2000);
            myThread.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

运行结果:

 

虽然有多种方法使线程停止,但是还是建议通过catch语句块停止线程,因为catch语句块可以抛出异常到上层.

© 著作权归作者所有

scymore

scymore

粉丝 6
博文 34
码字总数 22032
作品 0
成都
程序员
私信 提问
Posix多线程编程学习笔记

Posix多线程编程学习笔记(一)—线程基础(1) http://blog.chinaunix.net/u/22935/showart_310711.html Posix多线程编程学习笔记(一)—线程基础(2) http://blog.chinaunix.net/u/2293...

晨曦之光
2012/04/13
240
0
C#多线程学习(五) 多线程的自动管理(定时器)

本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线...

Yamazaki
2012/03/29
23
0
C#多线程学习(二) 如何操纵一个线程

[1] C#多线程学习(二) 如何操纵一个线程 [2]C#多线程学习(二) 如何操纵一个线程 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生...

Yamazaki
2012/03/29
12
0
C#多线程学习(六) 互斥对象

本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线...

Yamazaki
2012/03/29
8
0
C#多线程学习(三) 生产者和消费者

[1] C#多线程学习(三) 生产者和消费者 [2]C#多线程学习(三) 生产者和消费者 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者...

Yamazaki
2012/03/29
19
0

没有更多内容

加载失败,请刷新页面

加载更多

如何有效地计算JavaScript中对象的键/属性数量?

计算对象的键/属性数的最快方法是什么? 是否可以在不迭代对象的情况下执行此操作? 即不做 var count = 0;for (k in myobj) if (myobj.hasOwnProperty(k)) count++; (Firefox确实提供了一...

技术盛宴
25分钟前
3
0
百度网址安全中心拦截解除的办法分享

临近2019年底,客户的公司网站被百度网址安全中心拦截了,公司网站彻底打不开了,影响范围很大,于是通过朋友介绍找到我们SINE安全公司寻求帮忙解封,关于如何解除百度的安全拦截提示,下面就...

网站安全
36分钟前
3
0
Tomcat8源码分析-启动流程-start方法

上一篇:Tomcat8源码分析-启动流程-load方法 前面讲了启动流程中的Catalina.load,进一步调用绝大部分组建的init操作,主要完成对server.xml解析,并根据解析的结果结合设置的Rule(规则)构造...

特拉仔
45分钟前
6
0
Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍

Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍 轻拍标签栏中的About标签,进入关于页面,如图1.8和图1.9所示。它是对应用程序介绍的页面。 该页面源自Views文件夹中的AboutPage.x...

大学霸
51分钟前
3
0
一步一步理解Impala query profile(一)

很多Impala用户不知道如何阅读Impala query profile来了解一个查询背后正在执行的操作,从而在此基础上对查询进行调优以充分发挥查询的性能。因此我想写一篇简单的文章来分享我的经验,并希望...

九州暮云
52分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部