1、线程停止概述
Thread类中stop方法已经过时;
如何停止线程?
只有一种,就是让run方法结束;只要控制住循环,就可以让run方法结束,也就是线程结束。
开启多线程运行,运行代码通常为循环结构。
以下为一种简单的让线程停止的代码:
public class StopTest implements Runnable
{
private boolean flag=true;
public void run()
{
while(flag)
{
//try{Thread.sleep(100);}catch(Exception e){}
System.out.println("...."+Thread.currentThread().getName());
}
}
public void changeFlag()
{
flag=false;
}
}
public class StopDemo
{
public static void main(String[] args)
{
int i=0;
StopTest t=new StopTest();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
t2.start();
while(true)
{
//try{Thread.sleep(100);}catch(Exception e){}
if(i++==60)
{
t.changeFlag();
break;
}
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}
特殊情况:
但是如果碰到wait或者await方法,则会进入冻结状态,此时不会读取到标记,那么线程就不会结束,如下代码import java.util.concurrent.locks.*;
public class StopTest implements Runnable
{
private boolean flag=true;
private Lock lock=new ReentrantLock();
private Condition c=lock.newCondition();
public void run()
{
while(flag)
{
lock.lock();
//try{c.await();}catch(InterruptedException e){}
try{Thread.sleep(100);}catch(Exception e){}
System.out.println("...."+Thread.currentThread().getName());
lock.unlock();
}
}
public void changeFlag()
{
flag=false;
}
}
2、Interrupt方法
正常唤醒方法有notify、signal方法;
Thread类提供interrupt唤醒方法;
注意:interrupt方法不是正常唤醒,是强制唤醒;
代码如下:
import java.util.concurrent.locks.*;
public class StopTest implements Runnable
{
private boolean flag=true;
private Lock lock=new ReentrantLock();
private Condition c=lock.newCondition();
public void run()
{
while(flag)
{
lock.lock();
try{Thread.sleep(1);} //睡眠冻结,将sleep中的时间通过不断的调整,可以得到不同的结果!
catch(Exception e){System.out.println(Thread.currentThread().getName()+"....Sleep");}
try{c.await();} //等待冻结
catch(InterruptedException e){System.out.println(Thread.currentThread().getName()+".....Exception");}
System.out.println("...."+Thread.currentThread().getName());
lock.unlock();
}
}
public void changeFlag()
{
flag=false;
}
}
public class StopDemo
{
public static void main(String[] args)
{
int i=0;
StopTest t=new StopTest();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
t2.start();
while(true)
{
try{Thread.sleep(10);}catch(Exception e){}
if(i++==10)
{
t.changeFlag();
t1.interrupt(); //t1唤醒
t2.interrupt(); //t2唤醒
break;
}
System.out.println(Thread.currentThread().getName()+"..."+i);
}
try{Thread.sleep(1);}catch(Exception e){}
t1.interrupt(); //t1唤醒
t2.interrupt(); //t2唤醒
System.out.println("over");
}
}
其强制唤醒机制是,通过interrupt方法强制唤醒在sleep或者await中冻结的线程,以如下运行结果为例:
2.1、将红色不部分sleep参数设置为1,结果如下:
其过程为,t1、t2线程在执行后,先sleep()1ms,由于main线程sleep()10ms,所以主线程运行至判断i++==10之前,t1、t2线程已经进入await(),然后被interrupt中断,报出异常,然后处理异常,然后继续执行下一句;
2.2、将红色不部分sleep参数设置为10,结果如下:
其过程为:
- t1、t2线程在执行后,先sleep()100ms,由于main线程sleep()10ms,所以主线程运行至判断i++==10之前,t1线程已经进入await(),但是t2线程还在sleep();
- 主线程将标志位置为false,同时开启两个中断唤醒!
- t2的sleep冻结状态然后被interrupt中断,报出异常,然后处理异常,然后继续执行下一句;然后t2又进入await()冻结状态;
- t1的await冻结状态被interrupt中断,报出异常,然后处理异常,继续执行下一句,循环判断标志位,t1线程结束;
- 主线程中在sleep()1ms后,又产生两个中断唤醒,其中t2的中断将t2唤醒,报出异常,然后异常处理,继续执行下一句,循环判断标志位,t2线程结束。
2.3、将红色不部分sleep参数设置为200,结果如下:
过程如2.2分析,只不过这次两个都是在sleep()冻结状态!