• JAVA处理线程超时


    在实际业务中,由其是多线程并开业务中,经常会遇到某个线程执行超时。而程序如果不捕获这类情况,就会导致程序一直处于等待状态,从而影响后续线程的运行。
    比如说网络通迅、单任务下的复杂数据库查询等,通常处理这类问题,可以启用一个后台守护线程来监控用户线程(业务线程)的执行是否超时,如果超时就不在等待,这种做法,通常是在调用用户线程的.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;
     }

    }


  • 相关阅读:
    JDBC学习笔记
    hdfs文件格式
    全国疫情防控监控平台开发
    MySQL学习笔记
    拖拽表单生成
    Cython加密(含Windows和Linux)
    pcl 文字点云
    新装Ubuntu系统--常用软件安装配置
    GIT
    Data Analysis With Python
  • 原文地址:https://www.cnblogs.com/kuyuyingzi/p/4266328.html
Copyright © 2020-2023  润新知