java停止线程

1.停止线程

有三种方法可以终止正在运行的线程

1)使用退出标志,使线程运行run正常退出

2)使用stop(),但不推荐,他和suspend和resume一样,都是作废的方法

3)使用interrupt方法中断线程

使用java内置支持多线程的类设计多线程应用是很常见的事情,然而处理不好就会导致超出预期的·行为并且难以定位错误

1.1 停止不了的线程

package mythread;

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

package mythread;

public class run3 {
	public static void main(String[] args) {

		try {
			Thread3 t3=new Thread3();
			t3.start();
			Thread.sleep(2000);
			t3.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		
	}

}

结果

i=499983
i=499984
i=499985
i=499986
i=499987
i=499988
i=499989
i=499990
i=499991
i=499992
i=499993
i=499994
i=499995
i=499996
i=499997
i=499998
i=499999
i=500000

注:调用intertupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真正的停止线程;

1.2 判断线程是否是停止状态

1)this.interrupted();测试当前线程是否已经中断

    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

2)this.isInterrupted():判断线程是否已经中断

    public boolean isInterrupted() {
        return isInterrupted(false);
    }

修改上面测试代码

 

package mythread;

public class run3 {
	public static void main(String[] args) {

		try {
			Thread3 t3=new Thread3();
			t3.start();
			Thread.sleep(2000);
			t3.interrupt();
			System.out.println("是否停止1 "+t3.interrupted());
			System.out.println("是否停止2 "+t3.interrupted());

		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		
	}

}

结果

i=994
i=995
i=996
i=997
i=998
i=999
i=1000
是否停止1 false
是否停止2 false

测试当前线程是否中断,这个当前线程是main,从未中断,所以输出false;

现在停止main线程

package mythread;

public class run3 {
	public static void main(String[] args) {

		//			Thread3 t3=new Thread3();
		//			t3.start();
		//			Thread.sleep(2000);
		//			t3.interrupt();
					Thread.currentThread().interrupt();
					System.out.println("是否停止1 "+Thread.interrupted());
					System.out.println("是否停止2 "+Thread.interrupted());
		
	}

}

结果:

是否停止1 true
是否停止2 false


 注:interrupted()是测试当前线程是否中断,并清除线程的中断状态

isInterrupted()

测试线程Thread对象是否已经是中断状态,但不清除状态标记;

1.3 能停止的线程---异常法

package mythread;

public class Thread3 extends Thread{
	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("end");
	}
}


package mythread;

public class run3 {
	public static void main(String[] args) {

		try {
			Thread3 t3=new Thread3();
			t3.start();
			Thread.sleep(2000);
			t3.interrupt();
			//Thread.currentThread().interrupt();
//			System.out.println("是否停止1 "+Thread.interrupted());
//			System.out.println("是否停止2 "+Thread.interrupted());
//			System.out.println("是否停止1 "+t3.isInterrupted());
//			System.out.println("是否停止2 "+t3.isInterrupted());

		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		
	}

}

结果

i=263345
i=263346
i=263347
线程中断退出
end


 注:线程输出end说明线程并没有停止,修改线程run方法

package mythread;

public class Thread3 extends Thread{
	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("end");
		} catch (InterruptedException e) {
			System.out.println("进入run catch");
			e.printStackTrace();
		}
		
	}
}


输出结果:

i=277141
线程中断退出
进入run catch
java.lang.InterruptedException
	at mythread.Thread3.run(Thread3.java:11)

1.4 在沉睡中停止

package mythread;

public class Thread4 extends Thread{
	public void run(){
		try {
			System.out.println("run begin");
			Thread.sleep(20000);
		} catch (InterruptedException e) {
			System.out.println("在沉睡中终止会进入catch "+this.isInterrupted());
			e.printStackTrace();
		}
	}

}


package mythread;

public class run4 {
	public static void main(String[] args) {

		try {
			Thread4 t4=new Thread4();
			t4.start();
			Thread.sleep(200);
			t4.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		System.out.println("main end");
	}

}

结果:

 

run begin
main end
在沉睡中终止会进入catch false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at mythread.Thread4.run(Thread4.java:7)

注:如果在sleep状态下停止某一线程,会进入catch里面去,并清除停止状态值。

与之相反,先停止再sleep也会进入catch里去,并清除停止状态值;

1.5 能停止的线程---暴力停止

package stopMethod;

public class Thread1 extends Thread{
	private int i=0;
	public void run(){
		try {
			while(true){
				i++;
				System.out.println(i);
				Thread.sleep(1000);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
		}
	}

}
package stopMethod;

public class Run1 {
	public static void main(String[] args) {
		try {
			Thread1 t1=new Thread1();
			t1.start();
			Thread.sleep(8000);
			t1.stop();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}

}


结果

1
2
3
4
5
6
7
8

1.6 方法stop()与java.lang.ThreadDeath异常

调用stop会跑出java.lang.ThreadDeath,但通常情况下,此异常不需要显示的捕捉

package stopMethod;

public class Thread2 extends Thread{
	public void run(){
		try{
			this.stop();			
		}catch(ThreadDeath e){
			System.out.println("进入stop catch里面去了");
			e.printStackTrace();
		}
		
	}

}
package stopMethod;

public class Run2 {
	public static void main(String[] args) {
		Thread2 t2=new Thread2();
		t2.start();		
	}


}

结果:

 

进入stop catch里面去了
java.lang.ThreadDeath
	at java.lang.Thread.stop(Thread.java:813)
	at stopMethod.Thread2.run(Thread2.java:6)


注:方法stop已经作废,如果强制让线程停止则可能使一些清理性的工作得不到完成,

另外一个情况就是对锁定的对象进行“解锁”,导致数据得不到同步的处理,出现数据不一致的情况。

1.7 释放锁的不良后果

package stopMethod;

public class SynchronizedObject {
	private String username="a";
	private String password="aa";
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	synchronized public void printObject(String name,String pwd){
		try {
			this.username=name;
			Thread.sleep(10000);
			this.password=pwd;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}

}


package stopMethod;

public class Thread3 extends Thread{
	private SynchronizedObject object;
	public  Thread3(SynchronizedObject object){
		super();
		this.object=object;
	}
	public void run(){
		object.printObject("b", "bb");
	}

}


package stopMethod;

public class Run3 {
	public static void main(String[] args) {
		try {
			 SynchronizedObject object=new  SynchronizedObject();
			 Thread3 t3=new Thread3(object);
			 t3.start();
			 Thread.sleep(200);
			 t3.stop();
			System.out.println(object.getUsername()+" "+object.getPassword());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

}


输出结果:

b aa

注:使用stop()释放锁会给数据造成不一致性的结果,如果出现这样额结果,陈旭处理的结果就有可能遭到破坏,最终导致程序执行流程出错,

该方法已经在jdk中作废,显然它在功能上有缺陷。

1.8 使用return停止线程

将方法interrupt与return结合使用也能实现停止线程的效果 

package stopMethod;

public class Thread4 extends Thread{
	public void run(){
		while(true){
			if(this.isInterrupted()){
				System.out.println("停止了。。");
				return;
			}
			System.out.println(System.currentTimeMillis());
		}
	}
}
package stopMethod;

public class Run4 {
	public static void main(String[] args) {
		try {
			Thread4 t4=new Thread4();
			t4.start();
			Thread.sleep(1000);
			t4.interrupt();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}

}


输出结果:

1473999594715
1473999594715
1473999594715
1473999594715
停止了。。


注:不过还是建议使用“抛异常”的方法来停止线程。因为在catch块中可以对异常的信息进行相关的处理,而且使用异常能更好的更方便控制流程的运行流程,

不至于代码中出现多个return,造成污染。
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值