您的位置:首页 > 编程语言 > Java开发

Java停止线程及有锁时停止方法

2017-01-07 16:15 183 查看
当我们刚学完Thread一个线程t1之后,迫不及待地键入t1.start()开始启动线程,肯定思考过如何将这个线程停下来

其实原理只有一个,那就是让run方法结束

要知道开启多线程运行,其运行代码通常都是循环结构,只要控制住循环就可以让run方法结合苏,也就是线程结束

比如写个代码

class StopThread implements Runnable
{
public synchronized void  run()
{
while(true)
{
System.out.println(Thread.currentThread().getName()+"...run");
}
}
}
public class StopThreadDemo {
public static void main(String[] args) {
StopThread st=new StopThread();
Thread t1=new Thread(st);
Thread t2=new Thread(st);
t1.start();
t2.start();
int num=0;
while(true)
{
if(num++==60)
{
break;
}
System.out.println(Thread.currentThread().getName()+"......"+num);
}
}
}


这个小程序很简单,就是让两个线程一直跑,跑到60次之后就break,想法是好的,这个程序我是不会去跑的,因为我知道这个是无限循环,while(true)这个标记让它一直转

所以如果while(true)这个标记能够控制住,这个小程序就能停下来

可以定义个flag=true,再定义个changeFlag()方法,这个方法里面将flag切换为false

将while(true)改为while(false)

如果num++=60,就调用changeFlag方法

class StopThread implements Runnable
{
private boolean flag=true;//**************
public void  run()
{
while(flag)//**************
{
System.out.println(Thread.currentThread().getName()+"...run");
}
}
public void changeFlag()//**************
{
flag=false;
}
}
public class StopThreadDemo {

public static void main(String[] args) {

StopThread st=new StopThread();
Thread t1=new Thread(st);
Thread t2=new Thread(st);
t1.start();
t2.start();
int num=0;
while(true)
{
if(num++==60)
{
st.changeFlag();//**************
break;
}
System.out.println(Thread.currentThread().getName()+"......"+num);
}
}
}




但是有一种情况,程序也停不下来

就是同步

public synchronized void  run()
{
while(flag)//**************
{

try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"...Exception");
flag=false;
}
System.out.println(Thread.currentThread().getName()+"...run");
}
}


*run()方法若是同步函数,且在while内try一个wait(),抛出InterruptedException,这时候运行也做了changeFlag()改变,程序就不会停下来;



如图,程序没有停下来,但是并不占用资源,不是死循环,因为wait在那儿了

当主线程while(true)的时候一直在转,到num==60的时候,st.changeFlag()也读了。可是开启两个线程之后,无论什么时候抢到CPU资源,都去public

synchronized void run(){}里面去运行

Thread-0进去之后,拿到一把锁,然后wait()了,放弃了资格,然后Thread-1进去也释放资格了,然后这两个都挂在这儿不动了;

主线程执行完了,还有两个线程存活,这个就是问题,改变了标记flag但是没有结束线程

也就是当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。

**只有wait()结束之后再去while(flag)循环,读到标记才能结束。

我们可以强制做这件事情

在Thread中提供了一个方法叫interrupt()方法,叫做中断线程:如果线程在调用Object类的wait()等方法,或者join和sleep受阻,则其终端状态江北清除;中断状态也就是Wait,还会收到一个InterruptException;但是中断并不是stop,只是挂起

这时候,我可以强制清除其中断状态,强制地恢复到运行状态
4000


wait就像是催眠,催眠师拿个表将他吹眠之后进入中断状态,随后又用他的方法把他叫醒了;但现在,催眠师又把他催眠到中断状态,然后出国了。。。这时候要他醒过来怎么办,我又不会催眠师的方法,那我就一砖头下去把他呼醒得了

但是受伤了,发生异常了

现在对t1和t2下手,改变主函数的if内部:

if(num++=60)
{
t1.interrupt();
t2.interrupt();
st.changeFlag();
break;
}


完整如下:

class StopThread implements Runnable
{
private boolean flag=true;
public  synchronized void  run()
{
while(flag)
{
try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"...Exception");
//flag=false;
}
System.out.println(Thread.currentThread().getName()+"...run");
}
}
public void changeFlag()
{
flag=false;
}
}
public class StopThreadDemo {

public static void main(String[] args) {

StopThread st=new StopThread();
Thread t1=new Thread(st);
Thread t2=new Thread(st);
t1.start();
t2.start();
int num=0;
while(true)
{
if(num++==60)
{
t1.interrupt();
//st.changeFlag();
break;
}
System.out.println(Thread.currentThread().getName()+"......"+num);
}
System.out.println("over");
}
}




看打印结果,Thread-0出现了终端异常,这就是因为t1的中断状态被强制清除了,所以产生了中断异常,但是程序还挂着不动,可以看到catch到异常之后又处理了一次,打印了Thread_0…run,之后此线程又回到了while(flag), 此时flag依旧为true,接着wait,又挂了

所以知道这个原因之后就很好解决了,

也就是只要发生异常,就代表有人在强制清除其中断状态,那么就在处理这个异常的时候,将flag标记为false,就可以完美结束了。

class StopThread implements Runnable
{
private boolean flag=true;
public synchronized void  run()
{
while(flag)
{
try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"...Exception");
flag=false;
}
System.out.println(Thread.currentThread().getName()+"...run");
}
}
public void changeFlag()
{
flag = false;
}
}

public class StopThreadDemo {

public static void main(String[] args) {

StopThread st=new StopThread();
Thread t1=new Thread(st);
Thread t2=new Thread(st);
t1.start();
t2.start();
int num=0;
while(true)
{
if(num++==60)
{
t1.interrupt();
t2.interrupt();
st.changeFlag();
break;
}
System.out.println(Thread.currentThread().getName()+"......"+num);
}
System.out.println("over");
}

}


总结就是

当没有指定的方法让冻结的线程恢复到运行状态时,这就需要对冻结进行清除

强制让线程恢复到运行状态中来,就可以操作标记flag,让线程结束

Thread类提供该方法,interrupt( );
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 线程 多线程 结构