• 前言
  • 停止线程
  • 使用stop()方法
  • 代码实例
  • stop()存在的问题
  • 使用interrupt()中断线程
  • 实例代码
  • interrupted()和isInterrupted()
  • 暂停线程
  • 实例代码
  • suspend(),resume()存在的问题
  • yield()方法使线程暂停


前言

 在Java中有几种方式会使线程结束运行.
 1.线程执行任务完毕,正常退出;
 2.线程遭遇异常,释放所占用的锁,并退出;
 3.线程调用stop()方法,强制终止线程;
 4.线程使用interrupt方法中断线程.
 本文章主要讨论使用stop方法和interrupt方法退出线程,并讲述如何暂停线程.
 完整代码

停止线程

使用stop()方法

代码实例

package org.StopThread;

public class StopThread {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //使用stop停止线程
        System.out.println("执行主线程");
        User user = new User();
        Thread1 th1 = new Thread1(user);
        Thread1 th2 = new Thread1(user);
        th1.start();
        th2.start();
        try {
            Thread.sleep(10);
        } catch (Exception e) {
        }
        th1.stop();
        try {
            Thread.sleep(10);
        } catch (Exception e) {
        }
        System.out.println("主线程执行结束");
    }
}
class User{

    synchronized public void getName() {
        System.out.println(Thread.currentThread().getName() + "获得锁");
        try {
            Thread.sleep(200);
        } catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println(Thread.currentThread().getName() + "释放锁");
    }
}
class  Thread1 extends Thread{
    User user;  
    public Thread1(User user) {
        super();
        this.user = user;
    }
    @Override
    public void run() {

        //this.stop();
        int i = 0 ;     
        while(true) {
            user.getName();
            System.out.println(Thread.currentThread().getName() + " i  = " + (i++));            
        }
    }
}

输出

执行主线程
Thread-0获得锁
Thread-1获得锁
主线程执行结束
Thread-1释放锁
Thread-1 i  = 0
Thread-1获得锁
Thread-1释放锁
Thread-1 i  = 1
Thread-1获得锁
Thread-1释放锁

当执行stop()方法后,Thread-0立即停止,并且释放锁,Thread-1获得锁.
同时Thread-0会抛出ThreadDeath异常.

stop()存在的问题

stop()在如今的JDK中已经不推荐使用.因为如果强制让线程停止:
1.则有可能会导致一些清理性的工作无法完成,比如释放资源等.
2.另外的一种情况是对锁定的对象进行了解锁,导致数据的报道同步的处理,会出现数据不一致的情况.

使用interrupt()中断线程

实例代码

package org.StopThread;

public class InterruptThread {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("执行主线程");
        Thread2 th1 = new Thread2();
        th1.start();
        try {
            Thread.sleep(1000);
         } catch (Exception e) {
        }
        System.out.println(th1.getName() + "interrupt");
        th1.interrupt();
        System.out.println("线程是否中断? " + th1.isInterrupted());
        System.out.println("线程是否中断? " + th1.isInterrupted());
    }

}

class  Thread2 extends Thread{

    @Override
    public void run() {
        int i = 0 ;     
        System.out.println(Thread.currentThread().getName() + "执行!");
        while(true) {
            /*if(this.interrupted()) {
                System.out.println(Thread.currentThread().getName() + "产生中断,线程退出执行");
                break;
            }*/

        }
    }
}

输出

执行主线程
Thread-0执行!
Thread-0 interrupt
线程是否中断? true
线程是否中断? true

使用isInterrupted()判断线程是否进入中断,执行th1.interrupt();并不能使线程结束运行,只是告知线程有一个中断请求,线程不断地检测中断状态,以便进行相应地操作.比如停止线程操作.
停止线程操作:不断地检测中断状态,如果产生中断,使用return或者break结束线程运行.

while(true) {
    if(this.interrupted()) {
        System.out.println(Thread.currentThread().getName() + "产生中断,线程退出执行");
        break;
    }
}

interrupted()和isInterrupted()

interrupted:测试当前线程是否有中断,并且清除中断状态;(在哪个线程中调用就判断哪个线程的中断状态,比如在main线程调用th1.interrupted()判断的是main线程的中断状态)
isInterrupted:测试调用的线程是否有中断,不清除中断状态;(哪个线程调用就判断哪个线程的中断状态,比如在任何线程中调用th1.isInterrupted()判断的都是th1线程的中断状态).

暂停线程

暂停线程使用Thread中的suspend()方法;
恢复暂停的线程使用resume()方法,这两个方法已经不推荐使用了.

实例代码

package org.StopThread;

public class SuspendThread {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Thread3 th3 = new Thread3();
        System.out.println(th3.getName() + "启动");
        th3.start();


        try {
            Thread.sleep(100);
        } catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println(th3.getName() + "暂停");
        th3.suspend();

        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println(th3.getName() + "恢复执行");
        th3.resume();   
    }

}

class  Thread3 extends Thread{  
    @Override
    public void run() {
        int i = 0 ;     
        System.out.println(this.getName() + "执行!");
        while(true) {
            System.out.println(System.currentTimeMillis());
            try {
                Thread.sleep(20);
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    }
}

输出

Thread-0启动
Thread-0执行!
1529852315885
1529852315905
1529852315925
1529852315945
1529852315966
Thread-0暂停
Thread-0恢复执行
1529852316984
1529852317004
1529852317024

可以看出,线程暂停了差不多1000ms之后重新运行.

suspend(),resume()存在的问题

class  Thread4 extends Thread{  

    private People people;

    public Thread4(People people) {
        super();
        this.people = people;
    }

    @Override
    public void run() {
        int i = 0 ;     
        System.out.println(this.getName() + "执行!");
        while(true) {
            System.out.println(System.currentTimeMillis());
            System.out.println(this.getName() + " 请求锁......");
            people.func();
        }
    }
}
class People {

    synchronized public void func() {
        System.out.println(Thread.currentThread().getName() + "获取锁");
        try {
            Thread.sleep(100);
        } catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println(Thread.currentThread().getName() + "释放锁");
    }
}

测试

People people = new People();

Thread4 th4 = new Thread4(people);
Thread4 th5 = new Thread4(people);
System.out.println(th4.getName() + "启动");
th4.start();            
try {
    Thread.sleep(2);
} catch (Exception e) {
    // TODO: handle exception
}
System.out.println(th4.getName() + "暂停");
th4.suspend();

th5.start();

输出

Thread-0启动
Thread-0执行!
1529853126299
Thread-0 请求锁......
Thread-0获取锁
Thread-0暂停
Thread-1执行!
1529853126301
Thread-1 请求锁......

可以看出Thread-0暂停后,没再执行恢复操作,锁没有释放掉,导致Thread-1一直无法获取锁.
存在的问题:
1.存在死锁的可能性,比如上面的例子
2.有可能出现数据不一致的情况,因为数据可能被其他运行的线程更改.

yield()方法使线程暂停

public static native void yield();

yield()方法是Thread类的静态方法.
要使某个线程暂停,只要在线程运行体run()内调用即可.
会自动恢复运行.

Thread.yield()

yield()方法暂停的时间是不确定的,有可能刚暂停就又恢复执行.