终止线程

由于java放弃了自己的stop方法,导致我们终止一个线程变得困难[其实有stop也困难,可能导致死锁,你敢用哇?]。以下根据不同的情况,给出不同的解决办法。

1.线程里面是一个循环

这样的终止线程是最简单的,只需要设置一个标志位,在循环检查的时候,就可以跳出线程,代码如下:

package app; public class Main{ private static boolean run = true; public static void main(String[] args) { /** * 启动一个子线程 */ new Thread(new Runnable() { @Override public void run() { while (run) { System.out.println("running"); } } }).start(); try { Thread.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } /** * 终止子线程 */ run = false; } }

但是这样其实是“假终止”,很有可能,在我们设置停止线程的时候,线程跑了最后一次。

2.线程因为sleep,wait,join等方法进入“假死”状态

这种情况,我们可以借助于java多线程中的interrupt方法,产生一个InterruptedException异常,从而跳出线程。代码如下:

package app; public class Main { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { public void run() { while (true) { System.out.println("go to sleep"); try { Thread.sleep(2000); } catch (InterruptedException e) { continue;// break; } System.out.println("iiii am interrupted!"); } } }); thread.start(); thread.interrupt(); } }

3.线程因为获取网络数据等原因阻塞

在这里,暂时找不到让线程停止的方法,其实根据java多线程原理,多线程由虚拟机模拟,而线程一旦执行,是交给操作系统来完成的,所以,不管用什么方法,我们都不可能从系统级别终止一个启动的任务[就比如第一个例子中,如果进入while中,那这一次循环就不容易终止了]。但是很有可能其他线程在等待这个线程返回结果,而本线程又阻塞,那么这个时候折中的处理办法就是采用计时器,一旦超时,则通知等待线程。等待线程做出相应处理。

首先是一个计时器:

package app; /** * 计时器类,本质上就是一个监控“阻塞线程”的线程,要是“阻塞线程”超时,那么本线程通知等待线程 * */ public class Monitor extends Thread { private long timeout; private Timeable timeable; private long startTime; private boolean active = false; private boolean timing = false; private boolean bPaused = false; public Monitor(Timeable t, int timeout) { this.timeout = timeout; timeable = t; timing = false; } /** * 暂停计时器 */ public void pauseMonitor() { bPaused = true; } /** * 恢复计时器 */ public void resumeMonitor() { startTime = System.currentTimeMillis(); bPaused = false; } public void run() { active = true; while (active) { if (timing) { long tmp = System.currentTimeMillis() - startTime; if (!bPaused && (tmp) > timeout) { setTimeout(); } else { try { sleep(100); } catch (InterruptedException ie) { active = false; } } } else { try { sleep(100); } catch (Exception e) { e.printStackTrace(); active = false; } } } } /** * 开启计时器 */ public void startTimer() { if (!timing) { startTime = System.currentTimeMillis(); timing = true; } } /** * 超时以后,通知等待线程 */ public void setTimeout() { try { stopTimer(); timeable.timeout(); } catch (Exception ex) { } } /** * 停止计时器 */ public void stopTimer() { timing = false; } /** * 取消计时器 */ public void cancelTimer() { active = false; timing = false; } /** * 得到计时器设置的超时时长 */ public long getTimeout() { return timeout / 1000; } }

可能的阻塞线程类:

/** * 发送数据的线程,可能阻塞 * */ class SendThread implements Runnable, Timeable { private Monitor monitor = null; private int timeout; private MyListen myListen; /** * * @param send2Get * 消息接受者 * @param timeout * 超时时长:秒 */ public SendThread(MyListen myListen, int timeout) { this.myListen = myListen; this.timeout = timeout * 1000; } @Override public void run() { startTimer(); /** * 模拟超时 */ try { Thread.sleep(30000); //myListen.getInfo("准备接受数据"); } catch (InterruptedException e) { e.printStackTrace(); stopTimer(); } stopTimer(); } @Override public void cancelTimer() { if (monitor != null) { monitor.cancelTimer(); } } @Override public void startTimer() { monitor = getTimer(); monitor.startTimer(); } @Override public void stopTimer() { if (monitor != null) { monitor.stopTimer(); } } @Override public void timeout() { myListen.timeout("傻逼,不要等了,我超时了!"); } private Monitor getTimer() { if (monitor == null) { monitor = new Monitor(this, timeout); monitor.start(); } return monitor; } @Override public void pauseMonitor() { if (monitor != null) { monitor.pauseMonitor(); } } @Override public void resumeMonitor() { if (monitor != null) { monitor.resumeMonitor(); } } }

接收数据类:

class GetThread implements Runnable, MyListen { private int states = 0; private String str; @Override public void run() { while (true) { if (states == 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } else if (states == 1) { System.out.println(str); System.out.println("说话注意点,老子知道了"); break; } else if (states == 2) { System.out.println(str); System.out.println("一切正常,开始获取数据"); break; } } } @Override public void timeout(String str) { states = 1; this.str = str; } @Override public void getInfo(String info) { states = 2; this.str = info; } }

辅助接口:

package app; public interface Timeable { public void timeout(); public void startTimer(); public void stopTimer(); public void cancelTimer(); public void pauseMonitor(); public void resumeMonitor(); }

package app; public interface MyListen { public void timeout(String str); public void getInfo(String info); }

测试:

package app; public class Main { public static void main(String[] args) { GetThread getThread = new GetThread(); Thread thread_Get = new Thread(getThread); thread_Get.start(); new Thread(new SendThread(getThread, 5)).start(); } }

附加:

有些兄弟觉得Timer和TimerTask的组合可以做到终止线程[timer.cancle],是不正确的,它只可以把还没有执行的线程取消掉,但是并不能终止正在执行的线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值