Java线程停止方法-学习笔记

线程停止指线程处理完任务之前停掉正在进行的操作。

一、停止线程的方法

使用退出标志,使线程正常退出,即当run方法完成后终止线程。

使用stop强行终止线程,但不推荐此方法,可能产生不可预料的后果。

使用interrupt方法中断线程。

二、判断线程是否是停止状态

方法一:this.interrupted() 测试当前线程是否已经中断,当前线程指运行this.interrupted()方法的线程。

方法二:this.isInterrupted()测试线程是否已经中断。

实例一:

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

}
public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try
		{
			MyThread thread = new MyThread();
			thread.start();
			Thread.sleep(1000);
			thread.interrupt();
			System.out.println("Is stop 1?=" + thread.interrupted());
			System.out.println("Is stop 2?=" + thread.isInterrupted());
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
			
		}

	}

}

Output:

i=72493
i=72494
i=72495
Is stop 1?=false
i=72496
i=72497
i=72498
i=72499
i=72500
i=72501
i=72502
i=72503
i=72504
i=72505
i=72506
i=72507
i=72508
i=72509
i=72510
i=72511
i=72512
i=72513
i=72514
i=72515
i=72516
i=72517
i=72518
i=72519
Is stop 2?=true
i=72520

Tips:

从结果来看,线程并未停下来。因为interrupted()测试当前线程是否已经中断。

测试代码:使main线程产生中断

public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try
		{
			Thread.currentThread().interrupt();
			System.out.println("Is stop 1?=" + Thread.interrupted());
			System.out.println("Is stop 2?=" + Thread.interrupted());
		}
		catch(Exception e)
		{
			e.printStackTrace();
			
		}

	}

}

Output:

Is stop 1?=true
Is stop 2?=false

Tips:

方法的确判断出当前线程是停止状态,但由于线程中断状态会被interrupted()(这个方法是一个静态方法)清除,所以第二次调用返回了false。

而isInterrupted()方法并不会清除状态标识,所以多次调用不会有影响。

示例:判断线程是否是停止状态:

public class MyThread extends Thread{
	public void run()
	{
		super.run();
		for(int i=0;i<750000;i++)
		{
			if(this.interrupted())
			{
				System.out.println("has stopped.So will quit.");
				break;
			}
			System.out.println("i=" + (i+1));
		}
	}

}
public class App {

	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!");
	}
}

Output:

i=170457
i=170458
i=170459
i=170460
end!
has stopped.So will quit.

示例:线程沉睡中被停止

public class App {
	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{
	public void run()
	{
		try
		{
			super.run();
			System.out.println("run begin");
			Thread.sleep(20000000);
			System.out.println("run end");
		}
		catch(InterruptedException e)
		{
			System.out.println("be stopped and enter catch area when thread was sleeping." + this.isInterrupted());
			e.printStackTrace();
		}
	}

}

Output:

run begin
end!
be stopped and enter catch area when thread was sleeping.false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at P030.MyThread.run(MyThread.java:10)

Tips:

如果在sleep状态下停止某一线程,则会进入catch语句,并且会清除停止状态值,使之变成false。所以上面代码IsInterrupted()返回了false.

示例:测试先interrupt()后进入sleep()

public class MyThread extends Thread{
	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("be interruped!");
			e.printStackTrace();
		}
	}

}public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		MyThread thread = new MyThread();
		thread.start();
		thread.interrupt();
		System.out.println("end!");
	}

}

Output:

i= 99994
i= 99995
i= 99996
i= 99997
i= 99998
i= 99999
i= 100000
run begin
be interruped!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at P031.MyThread.run(MyThread.java:14)

Tips:

如果线程运行中被interrupt(),线程并不会立即停止,后续代码进入sleep()后,会抛出InterruptedException异常。

示例:stop()暴利停止线程

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

}
public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try
		{
		
			MyThread thread = new MyThread();
			thread.start();
			Thread.sleep(8000);
			thread.stop();
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}

	}

}

Tips:

即被stop后立即停止。

示例:stop()与ThreadDeath异常

public class MyThread extends Thread{
	public void run()
	{
		try
		{
			this.stop();
		}
		catch(ThreadDeath e)
		{
			System.out.println("enter catch method");
		}
	}

}

示例:使用return停止线程

public class MyThread extends Thread{
	public void run()
	{
		while(true)
		{
			if(this.isInterrupted())
			{
				return;
			}
		}
	}

}

Tips:相比于return,更建议使用抛异常的方法实现线程停止,因为catch可以处理异常信息,不至于代码出现多次return,造成代码污染。

疑问:

1、为什么线程interrupt()后,后续代码还在运行?

答:个人目前的理解是,当执行interrupt()方法后,线程只是被通知interrupt中断,改变线程interupted标识位。但是并不会立即杀死,具体过程,还需线程自己维护。(这也就解释了为什么Thread.Sleep()必须要加一个InterruptedException中断原因,因为在线程sleep状态下被中断会抛出异常,如果不在sleep状态,还会继续运行。如果有停止标识位,但是之前代码未处理,则会在sleep()中抛出。)