论坛贴吧问题:如何终止运行时间超时的线程
因为现在我要监控远程的一个方法,当这个方法执行超过一段时间时,我就要抛弃这个任务.那个方法我不能修改
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 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 方法
1 2 3 4 5 6 7 | public static void main(String[] args){ MyThreadPool threadPool = MyThreadPool.getInstance(); int availableTime = 5 ; MyWork b = new BWork(); threadPool.exeWork(b, availableTime); |
1 2 3 4 5 6 7 8 9 10 11 12 | public class BWork implements MyWork{ public boolean doSometing(){ System.out.println( "B starting..." ); //模拟远程的方法 最坏的情况是死循环 while ( true ){ } } } |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
回答:
1 worker 最好以以下的形式进行循环
1 2 3 4 5 6 7 8 9 | while ( true ) { if (Thread.currentThread().isInterrupted()) { return ; } // do something // thread sleep } |
这样打断该线程,以便结束该线程的生命周期。
其实executor.shutdown和shutdownnow也是调用thread.interupte来结束线程池的生命周期的
1 2 3 4 5 6 7 8 | // shutdownnow for (Worker w : workers) { w.interruptNow(); } // shutdown for (Worker w : workers) { w.interruptIfIdle(); } |
2 其实最简单的方法是设置所创建的thread为守护线程就可以了。
thread factory 生成thread的时候设置t.setDaemon(true);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 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()); |
以下是全部代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 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 最好以以下的形式进行循环
1 2 3 4 5 6 | while ( true ) { if (Thread.currentThread().isInterrupted()) { return ; } // do something } |
首先感谢你的回帖,但是有几点前提我需要澄清:
首先 我为什么把 work.doSomething() 抽象来 就是因为 那是我即将调用别人的方法,我没办法改,我要做的就是判断 doSomething 这个方法是否已经超时,如果超了 那就结束(或抛出)这个线程。
另外main 方法不应该提供对操作池的操作 因为是开放给其他人用的。
还有 我在网上找了几天资料,说线程 是没办法被 kill 的 那 tomcat又是如何做到抛出超时连接的呢?
https://github.com/godmaybelieve
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理