1.通过设置标志位方式停止线程
如下面代码所示,通过将标志为设置为false可以停止线程。
class myThread extends Thread
{
boolean flag = true;
public void run()
{
while(flag)
{
System.out.println("一直执行");
}
}
public void set()
{
flag = false;
}
}
class HighConcurrency
{
public static void main(String[] args) throws InterruptedException
{
myThread t1 = new myThread();
t1.start();
Thread.sleep(10); //这边要加一个睡眠,否则可能会导致先执行t1.set()方法
for(int i=0;i<1000;i++)
{
if(i==50)
{
t1.set();
}
}
}
}
缺点:当线程中sleep()方法,或者wait()调用的时候,IO阻塞(例如使用readLine()方法等待读取一个信息),这时候线程这种方法就不行了
2.通过中断方式退出线程
class MyThread extends Thread {
@Override
public void run() {
super.run();
try {
for (int i = 0; i < 500000; i++) {
if (this.isInterrupted()) {
System.out.println("已经是停止状态了!我要退出了!");
throw new InterruptedException(); //在收到中中断标志后,进入catch语句
}
System.out.println("i=" + (i + 1));
}
System.out.println("我在for下面"); //这段代码没有执行
} catch (InterruptedException e) {
System.out.println("进MyThread.java类run方法中的catch了!");
//e.printStackTrace();
}
}
}
public class TestJava {
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!");
}
}
代码执行结果:
i=260749
i=260750
i=260751
i=260752
i=260753
i=260754
已经是停止状态了!我要退出了!
end!
进MyThread.java类run方法中的catch了!
3.线程在sleep()状态遇到中断会抛出InterruptException
public class HighConcurrency {
public static void main(String args[]) throws InterruptedException {
Thread thread = new Thread() {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("收到中断信号,停止该线程!");
break;
}
try {
Thread.sleep(600);
} catch (InterruptedException e) { //在这里做些后续处理保证数据的一致性和完整性
e.printStackTrace();
Thread.currentThread().interrupt(); //或者使用this.interrupt()
}
System.out.println("Running!");
Thread.yield();
}
}
};
thread.start();
Thread.sleep(2000);
thread.interrupt();//进行中断操作
}
}
说明一:中断后,sleep()方法进入中断,注意此时if(Thread.currentThread().isInterrupt())并没有收到信号,因为是在sleep中断时进入catch语句的,所以在catch语句中再次中断当前线程,在if(Thread.currentThread().isInterrupt())语句中做后续的处理,保证数据的一致性和完整性。
为什么中断的时候,if(Thread.currentThread().isInterrput())没有收到中断信号,我的理解是sleep()被中断时会从中断sleep()方法会立即进入catch语句,但是注意,在抛出InterrputedException之前,Java虚拟机会先将线程的中断标识位清除,然后抛出interruptedException,所以在catch语句中再次中断,让其在if(Thread.currentThread().isInterrupted())中进行后续的处理。
说明二:run()方法中使用Thread.currentThread().interrupt()和this.interrupt()都是可以的,这里的this其实就是指的是调用该方法的对象,也就是thread线程,如果使用打印Thread.current().hashCode()和this.hashCode()会发现两者相同。
4.与线程中断的三个方法的说明:
public void interrupt() //中断线程
public boolean isInterrupted() //判断是否被中断
public static boolean interrupted() //判断是否被中断,并清除当前中断状态,这是一个静态方法
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 HighConcurrency {
public static void main(String[] args) {
Thread.currentThread().interrupt();
//中断后会清除中断标志
System.out.println("是否停止1?=" + Thread.interrupted()); //返回true 注意这是静态方法
System.out.println("是否停止2?=" + Thread.interrupted()); //返回false,注意因为上面的interrupt自动清除了标志位
Thread.currentThread().interrupt();
//中断后并未清除中断标志
System.out.println("是否停止1?=" + Thread.currentThread().isInterrupted()); //返回true 注意这不是静态方法,获取当前线程调用
System.out.println("是否停止2?=" + Thread.currentThread().isInterrupted()); //返回true
System.out.println("end!");
}
}
是否停止1?=true
是否停止2?=false
是否停止1?=true
是否停止2?=true
end!