资讯专栏INFORMATION COLUMN

Java超时控制的实现

dinfer / 2913人阅读

摘要:基本原理采用的和方法在另外一个线程中结果回来,一下,返回否则就等待超时返回超时采用一线程轮询的的双重保险实例参考

基本原理

采用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 FUTURES = new ConcurrentHashMap();
    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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65792.html

相关文章

  • SpringCloud(第 015 篇)电影Ribbon微服务集成Hystrix增加隔离策略控制指标

    摘要:传播安全上下文或使用,通过增加的属性,来增加相关的配置来达到执行隔离策略,控制线程数或者控制并发请求数来达到熔断降级的作用。 SpringCloud(第 015 篇)电影Ribbon微服务集成Hystrix增加隔离策略控制线程数或请求数来达到熔断降级的作用 - 一、大致介绍 1、本章节介绍关于Hystrix的2种隔离方式(Thread Pool 和 Semaphores); 2、Thr...

    RobinQu 评论0 收藏0
  • 使用SimpleTimeLimiter进行方法调用超时控制

    原理 利用Executors的Future的限时get方法,Google的SimpleTimeLimiter本质上是对Executors的Future的包装。 实例 package com.facebook.presto.raptor.backup; import com.facebook.presto.spi.PrestoException; import com.google.common....

    zhonghanwen 评论0 收藏0
  • Java

    摘要:当前线程在超时时间内被中断超时时间结束,返回释放锁获取等待通知组件,该组件和当前的锁绑定,当前线程只有获取了锁,才能调用该组件的方法,调用后,当前线程将释放锁。同步器是实现锁的关键,在锁的实现中聚合同步器,利用同步器实现锁的语义。 本文在参考java并发编程实战后完成,参考内容较多 Java中的锁 锁是用来控制多线程访问共享资源的方式,一个锁能够防止多个线程同事访问共享资源。在Lock...

    gaara 评论0 收藏0
  • Java多线程学习(四)等待/通知(wait/notify)机制

    摘要:运行可运行状态的线程获得了时间片,执行程序代码。阻塞的情况分三种一等待阻塞运行的线程执行方法,会把该线程放入等待队列中。死亡线程方法执行结束,或者因异常退出了方法,则该线程结束生命周期。死亡的线程不可再次复生。 系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键...

    PiscesYE 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<