导航

JAVA处理线程超时

Posted on 2013-12-24 18:57  酷鱼影子  阅读(302)  评论(0编辑  收藏  举报

在实际业务中,由其是多线程并开业务中,经常会遇到某个线程执行超时。而程序如果不捕获这类情况,就会导致程序一直处于等待状态,从而影响后续线程的运行。
比如说网络通迅、单任务下的复杂数据库查询等,通常处理这类问题,可以启用一个后台守护线程来监控用户线程(业务线程)的执行是否超时,如果超时就不在等待,这种做法,通常是在调用用户线程的.start()方法之前,调用守护线程的start()方法,同时将超时时长传给守护线程。在守护线程的run()方法,执行sleep()方法,休眠时间为超时时长,守护线程中有一个同步后的变量用于存储用户线程是否超时。而在用户线程中,在程序执行完之后,再调用守掮线程改变同步变量。当守护线程sleep()方法之后,去有判断同步变量的值是否已改变,如果没有改变,说明用户线程还未扫行完毕,也就是超时。但这种方法,不能中断用户线程。
除此之外,还有一种方法,可以中断用户线程不在继续运行,采用java.util.concurrent下面的接口、类也可以完成。以下是例子。

Java代码  收藏代码
  1. import java.util.concurrent.Callable;  
  2. import java.util.concurrent.ExecutionException;  
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5. import java.util.concurrent.Future;  
  6. import java.util.concurrent.TimeUnit;  
  7. import java.util.concurrent.TimeoutException;  
  8.   
  9. public class TimeOut {  
  10.     public static void main(String[] args){  
  11.         int timeout = 2//秒.  
  12.         ExecutorService executor = Executors.newSingleThreadExecutor();  
  13.         Boolean result = false;     
  14.         Future<Boolean> future = executor.submit(new MyJob("请求参数"));// 将任务提交到线程池中     
  15.         try {     
  16.             result = future.get(timeout*1000, TimeUnit.MILLISECONDS);// 设定在200毫秒的时间内完成   
  17.             System.out.println(result);  
  18.         } catch (InterruptedException e) {  
  19.             System.out.println("线程中断出错。");  
  20.             future.cancel(true);// 中断执行此任务的线程     
  21.         } catch (ExecutionException e) {     
  22.             System.out.println("线程服务出错。");  
  23.             future.cancel(true);// 中断执行此任务的线程     
  24.         } catch (TimeoutException e) {// 超时异常     
  25.             System.out.println("超时。");     
  26.             future.cancel(true);// 中断执行此任务的线程     
  27.         }finally{  
  28.             System.out.println("线程服务关闭。");  
  29.             executor.shutdown();  
  30.         }  
  31.     }  
  32.       
  33.     static class MyJob implements Callable<Boolean> {    
  34.         private String t;  
  35.         public MyJob(String temp){  
  36.             this.t= temp;  
  37.         }  
  38.         public Boolean call() {     
  39.             for(int i=0;i<999999999;i++){  
  40.                 if(i==999999997){  
  41.                     System.out.println(t);  
  42.                 }  
  43.                 if (Thread.interrupted()){ //很重要  
  44.                     return false;     
  45.                 }  
  46.             }   
  47.             System.out.println("继续执行..........");     
  48.             return true;     
  49.         }     
  50.     }   


在做socket通信时我这边服务端需要设置超时程序(客户端为硬件终端连接,没有回应几分钟内设置超时程序)

此socket服务端启动使用timertask类型,启动后再开几十个线程来处理终端连接。。。

我试了两种超时程序都蛮好:一种是通过线程的join设置,一种是通过concurrent的Future手段

join:

public class ThreadTest { 
    public static void main(String[] args) {   
        CounterThread ct = new CounterThread();   
        ct.start();
        try {   
            ct.join(20000);  //超时的时间,如20秒
            if(ct.isAlive()){//说明再设定的时间内没有执行完,超时
                  ct.interrupt(); 
                  throw new TimeoutException();//抛出,让socket线程终止
            }
            ct.getResult();//正常情况下可以获取执行后的值
        } catch (InterruptedException e) {   
            e.printStackTrace();   
        } 
    } 

class CounterThread extends Thread {   
    public CounterThread(int time) {  
         构造函数,传递一些有用的值给run;
    }  
    private int result;   
  
    public int getResult() {//在上面获取的结果值
        return result;   
    } 
    public void run() {   
               result = 执行的任务,如读取客户端数据; 
    }   

Furture:

public class TimeoutTest1 {

 public static void main(String[] args) {
  final ExecutorService service = Executors.newFixedThreadPool(1);

  TaskThread taskThread = new TaskThread();
  System.out.println("提交任务...begin");
  Future<Object> taskFuture = service.submit(taskThread);
  System.out.println("提交任务...end");
  try {
   Object re = taskFuture.get(6000, TimeUnit.MILLISECONDS);//超时设置,6s
   System.out.println(re);
  } catch (InterruptedException e) {
   e.printStackTrace();
  } catch (ExecutionException e) {
   e.printStackTrace();
  } catch (TimeoutException e) {
   System.out.println("超时 取消任务");
   taskFuture.cancel(true);
   System.out.println("超时 取消任务OK");
  } finally {
   service.shutdown();
  }

 }

}

class TaskThread implements Callable<Object> {

 public Object call() throws Exception {
  String result = "空结果";
  try {
   System.out.println("任务开始....");
   Thread.sleep(5000);
   result = "正确结果";
   System.out.println("任务结束....");
  } catch (Exception e) {
   System.out.println("Task is interrupted!");
  }
  return result;
 }

}