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

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


测试代码:

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

posted @ 2018-12-05 10:17  尐鱼儿  阅读(300)  评论(0编辑  收藏  举报