什么是等待延迟0的预定未来的最佳方式?

时间:2017-11-02 16:14:50

标签: java multithreading google-guava-cache

我试图避免睡眠当前线程,直到ScheduledFuture以0延迟执行。不幸的是,我无法找到一个反对未来的钩子,通知runnable何时执行。有问题的未来包装了一个guava cache.put(key,value)操作。应该在缓存到期之前调用runnable ...基本上,我希望一个密钥永不过期。

    final Runnable refresh = new Runnable() {
        @Override
        public void run()
        {
            cache.put( key, value );
        }
    };

    // replace the token when 95% of the ttl has passed
    long refreshInterval = (long)( keyExpires * 1000 *
                                   0.5 );

    // execute the future task and then delay the current thread long enough for the
    // executor to process the runnable. 50 ms should be long enough.
    ScheduledFuture<?> future = scheduler.scheduleAtFixedRate( refresh,
                                                               0,
                                                               refreshInterval,
                                                               TimeUnit.MILLISECONDS );

   /// this is the code I'd like to avoid
   try {
        Thread.sleep( 50 );
    } catch( InterruptedException e1 ) {} catch( ExecutionException e ) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

执行程序服务确实立即运行代码,但是有一个延迟时间来启动一个线程。该延迟将是系统特定的,所以我想避免任意睡眠。

我正在使用ScheduledThreadPoolExecutor来创建ScheduledFuture,我可以使用该类型的访问器获取我想要的行为,例如isDone()。然而,这看起来也很糟糕。是否有一个更清晰的实现提供睡眠当前线程的行为而不使用Executor服务的副作用?

谢谢, 罗宾

编辑:显示没有Thread.sleep()

的测试失败
    cache.putNonExpiring( "key", "value" );
    Assert.assertNotNull( "Immediate get should have value", cache.get( "key" ) );

要正常工作,应同步执行put(键,值)以允许立即获取(键)操作。

1 个答案:

答案 0 :(得分:1)

也许您可以使用当前线程阻塞的信​​号量或其他同步类型,直到刷新runnable释放信号量

// A semaphore initialized with no permits
final Semaphore runnableExecuting = new Sempahore(0);

final Runnable refresh = new Runnable()
{
    @Override
    public void run()
    {
        // Release one permit.  This should unblock the thread
        // scheduled this task.  After the initial releasing
        // the semaphore is essentially unneeded
        runnableExecuting.release();

        // Your code
    }
}

// After executor scheduling

// Attempt to acquire a permit, which the semphore initially has none.
// This will block until a permit becomes available
runnableExecuting.acquire();