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

What's the best way to wait on a scheduled future that has 0 delay?

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

    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(key,value) 以允许立即执行 get(key) 操作。

也许您可以使用当前线程阻塞的信​​号量或其他同步类型,直到 refresh 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();