- 前言
- 停止线程
- 使用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()方法暂停的时间是不确定的,有可能刚暂停就又恢复执行.