论坛贴吧问题:如何终止运行时间超时的线程
因为现在我要监控远程的一个方法,当这个方法执行超过一段时间时,我就要抛弃这个任务.那个方法我不能修改
测试代码:
public class MyThreadPool{ private static MyThreadPool myThreadPool = null; /*** 线程的最小数*/ private static int corePoolSize = 5; private static ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, corePoolSize*2,10,TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(corePoolSize),new ThreadPoolExecutor.AbortPolicy()); private MyThreadPool(){} public static MyThreadPool getInstance(){ if(null == myThreadPool){ System.out.println("MyThreadPool is creating!"); myThreadPool = new MyThreadPool(); } return myThreadPool; } /** * 执行任务 */ public void exeWork(final MyWork work,int availableTime){ FutureTask<Boolean> future = new FutureTask<Boolean>(new Callable<Boolean>(){ public Boolean call(){ return work.doSometing(); } }); executor.execute(future); try{ future.get(availableTime, TimeUnit.SECONDS); }catch(ExecutionException e1){ e1.printStackTrace(); }catch(InterruptedException e2){ e2.printStackTrace(); }catch(TimeoutException e3){ System.out.println("执行任务超时!"); }finally{ future.cancel(true); closeExecutor(); } } public void closeExecutor(){ if(executor != null && executor.getActiveCount() ==0 && executor.getQueue().isEmpty()){ executor.shutdown(); } } public static int getCorePoolSize() { return corePoolSize; } public static void setCorePoolSize(int corePoolSize) { MyThreadPool.corePoolSize = corePoolSize; } }
Main 方法
public static void main(String[] args){ MyThreadPool threadPool = MyThreadPool.getInstance(); int availableTime = 5; MyWork b = new BWork(); threadPool.exeWork(b, availableTime);
public class BWork implements MyWork{ public boolean doSometing(){ System.out.println("B starting..."); //模拟远程的方法 最坏的情况是死循环 while(true){ } } }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
回答:
1 worker 最好以以下的形式进行循环
while (true) { if (Thread.currentThread().isInterrupted()) { return; } // do something // thread sleep }
这样打断该线程,以便结束该线程的生命周期。
其实executor.shutdown和shutdownnow也是调用thread.interupte来结束线程池的生命周期的
// shutdownnow for (Worker w : workers) { w.interruptNow(); } // shutdown for (Worker w : workers) { w.interruptIfIdle(); }
2 其实最简单的方法是设置所创建的thread为守护线程就可以了。
thread factory 生成thread的时候设置t.setDaemon(true);
// t.setDaemon(true); private static ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, corePoolSize * 2, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(corePoolSize), new ThreadFactory() { public Thread newThread(Runnable r) { // TODO Auto-generated method stub final Thread t = new Thread(r); t.setDaemon(true); threads.add(t); return t; } }, new ThreadPoolExecutor.AbortPolicy());
以下是全部代码
package test.thread.csdn; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class InterupteThreadTest { private static InterupteThreadTest myThreadPool = null; private static int corePoolSize = 5; private static final List<Thread> threads = new ArrayList<Thread>(); private static ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, corePoolSize * 2, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(corePoolSize), new ThreadFactory() { public Thread newThread(Runnable r) { // TODO Auto-generated method stub final Thread t = new Thread(r); t.setDaemon(true); threads.add(t); return t; } }, new ThreadPoolExecutor.AbortPolicy()); private InterupteThreadTest() { } public static InterupteThreadTest getInstance() { if (null == myThreadPool) { System.out.println("MyThreadPool is creating!"); myThreadPool = new InterupteThreadTest(); } return myThreadPool; } /** * exeWork */ public void exeWork(int availableTime) { FutureTask<Boolean> future = new FutureTask<Boolean>( new Callable<Boolean>() { public Boolean call() { // dead loop mock while (true) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }); executor.execute(future); try { System.out.println(future.get(availableTime, TimeUnit.SECONDS)); } catch (ExecutionException e1) { e1.printStackTrace(); } catch (InterruptedException e2) { e2.printStackTrace(); } catch (TimeoutException e3) { System.out.println("timeout!"); } } public void shut() { executor.shutdown(); } /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { final InterupteThreadTest instance = InterupteThreadTest.getInstance(); instance.exeWork(4); instance.shut(); } }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
回复:
1 worker 最好以以下的形式进行循环
while (true) { if (Thread.currentThread().isInterrupted()) { return; } // do something }
首先感谢你的回帖,但是有几点前提我需要澄清:
首先 我为什么把 work.doSomething() 抽象来 就是因为 那是我即将调用别人的方法,我没办法改,我要做的就是判断 doSomething 这个方法是否已经超时,如果超了 那就结束(或抛出)这个线程。
另外main 方法不应该提供对操作池的操作 因为是开放给其他人用的。
还有 我在网上找了几天资料,说线程 是没办法被 kill 的 那 tomcat又是如何做到抛出超时连接的呢?
https://github.com/godmaybelieve