当前位置: 首页 > news >正文

Java超时控制的实现

基本原理

  • 采用LockSupport的parkNanos和unpack方法
  • 在另外一个线程中结果回来,unpack一下,返回;否则就等待超时返回(超时采用一线程轮询 + lock的condition的await 双重保险)

实例

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 
 * Created by codecraft on 2015/8/26.
 */
public class DefaultFuture {
    private static final Map<Long, DefaultFuture> FUTURES = new ConcurrentHashMap<Long, DefaultFuture>();
    private final long id;
    private final Lock lock = new ReentrantLock();
    private final Condition done = lock.newCondition();
    private volatile Response response;
    private final long start = System.currentTimeMillis();
    private final int timeout;
    public DefaultFuture(long id,int timeout) {
        this.id = id;
        this.timeout = timeout;
    }
    private long getStartTimestamp() {
        return start;
    }
    public int getTimeout() {
        return timeout;
    }
    public boolean isDone() {
        return response != null;
    }
    public long getId() {
        return id;
    }
    public Object get(int timeout){
        if (timeout <= 0) {
            timeout = 1000;
        }
        if (! isDone()) {
            long start = System.currentTimeMillis();
            lock.lock();
            try {
                while (! isDone()) {
                    done.await(timeout, TimeUnit.MILLISECONDS);
                    if (isDone() || System.currentTimeMillis() - start > timeout) {
                        break;
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
            if (! isDone()) {
//                throw new RuntimeException("timeout");
                System.out.println("timeout");
            }
        }
        return response;
    }
    private void doReceived(Response res) {
        lock.lock();
        try {
            response = res;
            if (done != null) {
                done.signal();
            }
        } finally {
            lock.unlock();
        }
    }
    public static void received(Response response) {
        try {
            DefaultFuture future = FUTURES.remove(response.getId());
            if (future != null) {
                future.doReceived(response);
            } else {
                System.out.println("The timeout response finally returned at "
                        + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()))
                        + ", response ");
            }
        } finally {
//            CHANNELS.remove(response.getId());
        }
    }
    private static class RemotingInvocationTimeoutScan implements Runnable {
        public void run() {
            while (true) {
                try {
                    for (DefaultFuture future : FUTURES.values()) {
                        if (future == null || future.isDone()) {
                            continue;
                        }
                        if (System.currentTimeMillis() - future.getStartTimestamp() > future.getTimeout()) {
                            // create exception response.
                            Response timeoutResponse = new Response(future.getId());
                            // handle response.
                            DefaultFuture.received(timeoutResponse);
                        }
                    }
                    Thread.sleep(30);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }
    }
    static {
        Thread th = new Thread(new RemotingInvocationTimeoutScan(), "ResponseTimeoutScanTimer");
        th.setDaemon(true);
        th.start();
    }
    public static void main(String[] args){
        int timeout = 1000;
        System.out.println("start");
        final long start = System.currentTimeMillis();
        final DefaultFuture future = new DefaultFuture(1,timeout);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (System.currentTimeMillis() - start < 2000) {
                    //sleep
                }
                Response response = new Response();
                response.setResult("hello");
                future.doReceived(response);
            }
        }).start();
        Object response = future.get(timeout);
        System.out.println(System.currentTimeMillis() - start);
        System.out.println("res "+response);
    }
}

参考

  • dubbo-DefaultFuture

相关文章:

  • HeadFirst设计模式(三) - 装饰者模式
  • PHP基本语法
  • linux下无法删除文件的原因
  • Python学习(18)面向对象
  • 神经网络学习入门 -01
  • Calendar获取时间的月和日
  • php提示 Notice: Use of undefined constant name - assumed
  • 深入理解ThreadLocal
  • 沫沫金:EasyUI 固定列
  • Intellij idea断点 Debugger slow: Method breakpoints my dramatically slow down debugging
  • 分布式高并发系统如何保证对外接口的幂等性?
  • CentOS6 图形界面(gnome)安装
  • 钉钉客户端JS-API权限签名算法.NET版
  • Linux 卸载mysql-libs包出现错误
  • .net中的Queue和Stack
  • 230. Kth Smallest Element in a BST
  • Angular6错误 Service: No provider for Renderer2
  • Go 语言编译器的 //go: 详解
  • JWT究竟是什么呢?
  • mysql中InnoDB引擎中页的概念
  • Node项目之评分系统(二)- 数据库设计
  • React 快速上手 - 07 前端路由 react-router
  • Sass 快速入门教程
  • Transformer-XL: Unleashing the Potential of Attention Models
  • zookeeper系列(七)实战分布式命名服务
  • 聊聊flink的BlobWriter
  • 每天10道Java面试题,跟我走,offer有!
  • 物联网链路协议
  • 优秀架构师必须掌握的架构思维
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 转载:[译] 内容加速黑科技趣谈
  • 白色的风信子
  • 7行Python代码的人脸识别
  • ​​​​​​​​​​​​​​Γ函数
  • (bean配置类的注解开发)学习Spring的第十三天
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (搬运以学习)flask 上下文的实现
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (四)图像的%2线性拉伸
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Core 和 .NET Framework 中的 MEF2
  • .Net Remoting常用部署结构
  • .NET Standard 的管理策略
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .net开发时的诡异问题,button的onclick事件无效
  • /etc/motd and /etc/issue
  • ??myeclipse+tomcat
  • @Import注解详解
  • [CareerCup][Google Interview] 实现一个具有get_min的Queue
  • [dart学习]第四篇:函数
  • [docker]docker网络-直接路由模式
  • [EFI]DELL XPS13 9360电脑 Hackintosh 黑苹果efi引导文件
  • [Electron]ipcMain.on和ipcMain.handle的区别