论坛贴吧问题:如何终止运行时间超时的线程

因为现在我要监控远程的一个方法,当这个方法执行超过一段时间时,我就要抛弃这个任务.那个方法我不能修改


测试代码:

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又是如何做到抛出超时连接的呢?

posted @   尐鱼儿  阅读(300)  评论(0编辑  收藏  举报
编辑推荐:
· 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编程运行原理
点击右上角即可分享
微信分享提示