Java多线程编程核心技术(一)停止线程的三种方法

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

 

  1. 使用退出标志,使线程正常退出,也就是让run()方法运行完成后停止
  2. 使用stop方法强行终止线程,但是不推荐使用这个方法,因为stop是作废过期的方法,使用它可能产生不可预料的结果
  3. 使用interrupt方法中断线程

下面分别看一下三种用法的区别:

1.使用退出标志让线程正常退出

package chapter1;

public class MyThread extends Thread{
	private  long i=0;
	private volatile boolean isRunning = true;

	@Override
	public void run(){
		while(isRunning){
			i++;
			System.out.println(i);
		}
	}
	public static void main(String[] args) throws InterruptedException {
		MyThread t = new MyThread();
		t.start();
		Thread.sleep(1000);
		t.isRunning=false;
		System.out.println("main end");
	}
}

控制台输出如下,可以看到在主线程中修改标记的值,使while循环停止,可以让线程t正常退出,推荐使用这种方法

184908
184909
184910
184911
184912
184913
184914
184915
main end

2.使用stop方法强制停止线程

package chapter1;

public class MyThread extends Thread{
	private  long i=0;
	

	@Override
	public void run(){
		while(true){
			i++;
			System.out.println(i);
		}
	}
	public static void main(String[] args) throws InterruptedException {
		MyThread t = new MyThread();
		t.start();
		Thread.sleep(1000);
		t.stop();
		System.out.println("main end");
	}
}

执行main方法,可以在控制台看到如下输出,也可以完成线程的停止。

181458
181459
181460
181461
181462
181463
181464
181465
181466
181467
main end

既然stop方法可以完成线程的停止,为什么jdk要废弃掉这个方法,不建议使用呢?我们看一下下面这个例子:

首先创建一个用户类,里面有一个同步方法updateUser,为了便于观察,模拟程序的执行时间,在两次set中间休眠了1秒

package chapter1;

public class User {
	private String username;
	private String password;
	
	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;
	}
	public User(String username, String password) {
		super();
		this.username = username;
		this.password = password;
	}
	
	synchronized public void updateUser(String u,String p){
		try {
			this.setUsername(u);
			Thread.sleep(1000);
			this.setPassword(p);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

接下来在主线程中我们执行0.5秒以后使用stop方法强制停止这个线程,观察执行结果

package chapter1;

public class MyThread extends Thread{
	private User user;

	public MyThread(User user) {
		super();
		this.user = user;
	}
	
	@Override
	public void run(){
		user.updateUser("b", "bb");
	}
	
	public static void main(String[] args) throws InterruptedException {
		User a = new User("a","aa");
		Thread t = new MyThread(a);
		t.start();
		t.sleep(500);
		t.stop();
		System.out.println("username:"+a.getUsername()+"  password:"+a.getPassword());
	}
}

控制台输出结果如下:

username:b  password:aa

使用stop方法会强制停止线程,不管当前线程在干什么都会被停止,使用stop暴力释放锁可能会导致数据不一致的问题。

3.使用interrupt方法来停止线程

interrupt方法并不会真的停止线程,只是对线程做一个标记,标记这个线程被中断了,所以需要和return或者抛异常的方法结合来使用。

package chapter1;

public class MyThread extends Thread{
	private volatile long i=0;

	@Override
	public void run(){
		try {
			while(true){
				i++;
				System.out.println(i);
				if(this.interrupted()){
//					throw new InterruptedException();
					return;
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void main(String[] args)  {
		
		try {
			MyThread t = new MyThread();
			t.start();
			Thread.sleep(1000);
			t.interrupt();
			System.out.println("main end");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

 

其实第一种和第三种方式是类似的,都是通过标记判断线程是否终止,然后使用return 或者throw a exception的方式来结束线程的执行,只不过interrupt不需要我们来定义标记。第二种方式使用stop方法太过于暴力,如果程序在执行一些很关键的操作,被强行终止,可能会发现意向不到的结果,最好还是不要使用。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值