1. 程式人生 > >論壇貼吧問題:如何終止執行時間超時的執行緒

論壇貼吧問題:如何終止執行時間超時的執行緒

因為現在我要監控遠端的一個方法,當這個方法執行超過一段時間時,我就要拋棄這個任務.那個方法我不能修改


測試程式碼:

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又是如何做到丟擲超時連線的呢?