Java中的多线程(四)之线程的停止

Java线程的停止,线程开启了,也许有时候我们需要停止线程的执行,总体来说,停止分两种,即:

1:正常停止,比如run方法执行完毕

2:非正常停止,可能被其它线程中断等等

OK,照例先看JDK中提供的方法

Java中的多线程(四)之线程的停止
Java中的多线程(四)之线程的停止Java中的多线程(四)之线程的停止
Java中的多线程(四)之线程的停止
我们可以看到interrupt和stop方法都可以停止线程,但是stop已经不建议使用了,我们探究下为什么不建议使用呢?看源代码:
 @Deprecated
    public final synchronized void stop(Throwable obj) {
        if (obj == null)
            ......
Java中的多线程(四)之线程的停止

  我们可以看到,第一点stop是一个synchronized的方法,那么前面在说synchronized关键字时,说到,一个类中的synchronized方法是没办法调用到另外一个synchronized方法的,因为两者需要的锁是相同的,所以如果我们把run方法设置为了synchronized,那么调用stop是没办法停止线程的。那么我们应该如何做呢?

具体内容请参考http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html,上面给我们提供了一些说明和替代方法。替代stop我们可以结合volatile和interrupt。

public class ThreadStopTest1 {
	public static void main(String[] args) throws Exception {
		MyThread1 t1 = new MyThread1();
		t1.startThread();
		Thread.sleep(3000);
		t1.stopThread();
	}
}
class MyThread1 extends Thread{
	private volatile boolean isRunning;
	
	public synchronized void startThread() {
		isRunning = true;
		this.start();
	}
	@Override
	public void run() {
		while(isRunning){
			//doSomething
			System.out.println("I am working");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("停止了");
	}
	public synchronized void stopThread() {
		isRunning = false;
	}
}
但是上面的程序是有问题的,因为其实质是在判断isRunning的值,如果轮询中的代码在wait、sleep时,其可能一直等待下去,这样,线程将无法停止,OK,我们加入interrupt,关于此关键字下一篇文章再说。修改代码如下:

public class ThreadStopTest2 {
	public static void main(String[] args) throws Exception {
		MyThread2 t1 = new MyThread2();
		t1.startThread();
		Thread.sleep(1000);
		t1.stopThread();
	}
}
class MyThread2 extends Thread{
	private volatile boolean isRunning;
	
	public synchronized void startThread() {
		isRunning = true;
		this.start();
	}
	@Override
	public void run() {
		long currentTime = System.currentTimeMillis();
		while(isRunning){
			System.out.println("I am working");
			try {
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				System.out.println("运行了" + (System.currentTimeMillis()-currentTime) / 1000 + "秒");
			}
		}
		System.out.println("停止了");
	}
	public synchronized void stopThread() {
		isRunning = false;
		this.interrupt();
	}
}
这样即使代码在sleep或者wait时,我们强行调用interrupt使线程抛出异常,从而达到目的。但是其实它还是有问题的,即如果代码不是在wait或者sleep,比如serversocket的accept,它会阻塞等待,这时interrupt是无法中断线程的,看代码:

public class ThreadStopTest2 {
	public static void main(String[] args) throws Exception {
		MyThread2 t1 = new MyThread2();
		t1.startThread();
		Thread.sleep(1000);
		t1.stopThread();
	}
}
class MyThread2 extends Thread{
	private volatile boolean isRunning;
	
	public synchronized void startThread() {
		isRunning = true;
		this.start();
	}
	@Override
	public void run() {
		long currentTime = System.currentTimeMillis();
		while(isRunning){
			System.out.println("I am working");
			try {
				ServerSocket sc  = new ServerSocket(80);
				System.out.println("将一直在等待着......");
				sc.accept();
			} catch (Exception e) {
				System.out.println("运行了" + (System.currentTimeMillis()-currentTime) / 1000 + "秒");
			}
		}
		System.out.println("停止了");
	}
	public synchronized void stopThread() {
		isRunning = false;
		this.interrupt();
	}
}

所以在实际代码中必须注意这些问题。

官方文章中推荐了另外一种写法,原理差不多,它用到了wait和notify,来模拟线程的暂停、恢复。这里不再贴代码,如果有需要可以参考那篇文章。

Java中的多线程(四)之线程的停止,布布扣,bubuko.com

Java中的多线程(四)之线程的停止

上一篇:Java中equals()和hashCode()的区别与联系


下一篇:java 中各种对象(po,vo,dto,bo)分类