最近在看Java多线程编程核心技术,也一直忘的比看的快,所以就做个笔记吧,概念性的东西就懒得提了
~~~~~~~~~~~~~~~~~~~~~~~~~~~
停止一个线程意味着在线程处理完任务之前停掉正在做的操作,也就是放弃当前的操作.
停止一个线程可以使用Thread.stop()方法,但是最好不要用它,虽然确实可以停止一个正在运行的线程,但是这个方式是不安全的并且被废弃的
大多数停止一个线程的操作使用Thread.interrupt()方法,尽管方法的名称是"停止、终止"的意思,但这个方法不会终止一个正在运行的线程,还需要加入一个判断才可以完成线程的停止.
在Java中有以下3种方法可以终止正在运行的线程:
1.使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
2.使用stop方法强制终止线程,但是不推荐,因为stop和suspend及resume一样都是过期的方法,会产生不可预料的结果.
3. 使用interrupt方法中断线程
停止不了的线程
调用interrupt方法来停止线程,但是interrupt方法的效果并不想for+break那样马上停止循环,调用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 Main {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
}
从运行结果上看,调用interrupt方法并没有停止线程。如何停止线程呢?
判断线程是否停止
如何判断线程的状态是不是停止的,在Java API中,Thread类提供了两种方法.
1. this.interrupted(): 测试当前线程是否已经中断。
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
2. this.isInterrupted(): 测试线程是否已经中断
public boolean isInterrupted() {
return isInterrupted(false);
}
两个都调用的是一个底层的 native的方法
private native boolean isInterrupted(boolean ClearInterrupted);
native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
那么这两个方法有什么区别呢? 先来看看this.interrupted()方法的解释:测试当前线程是否已经中断,当前线程是指运行this.interruped()方法的线程
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 Main {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.interrupt();
//Thread.currentThread().interrupt();
System.out.println("是否停止1?="+thread.interrupted());
System.out.println("是否停止2?="+thread.interrupted());
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
程序运行结果如下所示:
从控制台打印结果来看,线程并未停止,这也就证明的interrupted方法的解释,测试当前线程是否已经中断,这个当前线程是main,它从未中断过,所以结果是两个false
如何使main线程产生中断效果呢?
public class Main2 {
public static void main(String[] args) {
Thread.currentThread().interrupt();
System.out.println("是否停止1?=" + Thread.interrupted());
System.out.println("是否停止2?=" + Thread.interrupted());
System.out.println("end!");
}
}
结果:
从上述结果来看,方法interrupted()的确判断出当前线程是否是停止状态,但为什么第二个值是false呢?官方文档对interrupted方法的解释:
测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
文档已经解释得很详细,interrupted()方法具有清除状态的功能,所以第2次调用interrupted()方法返回的值是false。文档已经解释得很详细,interrupted()方法具有清除状态的功能,所以第2次调用interrupted()方法返回的值是false。
介绍完interrupted()方法后再来看一下isInterrupted()方法,声明如下:介绍完interrupted()方法后再来看一下isInterrupted()方法
public class Main3 {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.interrupt();
System.out.println("是否停止1?="+thread.isInterrupted());
System.out.println("是否停止2?="+thread.isInterrupted());
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
运行结果如下:
从结果中可以看到,方法isInterrupted()并未清除撞他标志,所以打印了两个true.
最后,再来看一下这两个方法的解释。
1. this.interrupted():测试当前线程是否已经中断状态,执行后具有将状态标志清除为false的功能。
2. this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志.
能停止的线程-异常法
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 500000; i++) {
if (this.interrupted()) {
System.out.println("已经是停止状态了!我要退出了!");
break;
}
System.out.println("i=" + (i + 1));
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 500000; i++) {
if (this.interrupted()) {
System.out.println("已经是停止状态了!我要退出了!");
break;
}
System.out.println("i=" + (i + 1));
}
System.out.println("我被输出,如果此代码是for又继续运行,线程并未停止!");
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
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("已经是停止状态了!我要退出了!");
throw new InterruptedException();
}
System.out.println("i=" + (i + 1));
}
System.out.println("我在for下面");
} catch (InterruptedException e) {
System.out.println("进MyThread.java类run方法中的catch了!");
e.printStackTrace();
}
}
}
在沉睡中停止
public class MyThread extends Thread {
@Override
public void run() {
super.run();
try {
System.out.println("run begin");
Thread.sleep(200000);
System.out.println("run end");
} catch (InterruptedException e) {
System.out.println("在沉睡中被停止!进入catch!"+this.isInterrupted());
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(200);
thread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
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("run begin");
Thread.sleep(200000);
System.out.println("run end");
} catch (InterruptedException e) {
System.out.println("先停止,再遇到了sleep!进入catch!");
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
thread.interrupt();
System.out.println("end!");
}
}
能停止的线程-暴力停止
public class MyThread extends Thread {
private int i = 0;
@Override
public void run() {
try {
while (true) {
i++;
System.out.println("i=" + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(8000);
thread.stop();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
使用return停止线程
public class MyThread extends Thread {
@Override
public void run() {
while (true) {
if (this.isInterrupted()) {
System.out.println("停止了...");
return;
}
System.out.println("timer=" + System.currentTimeMillis());
}
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread t=new MyThread();
t.start();
Thread.sleep(2000);
t.interrupt();
}
}
不过还是建议使用 抛异常 的方式来实现线程的停止,因为在catch块中可以对异常信息进行相关的处理,而且使用异常能更好的 更方便的控制程序的运行流程,不至于代码中出现很多个return;造成污染