【问题标题】:Using both timeout and semaphore for Thread blocking使用超时和信号量进行线程阻塞
【发布时间】:2015-07-10 20:53:59
【问题描述】:

我有一种运行方法可以连接到服务器,当服务器出现故障时,会等到它收到服务器再次启动的消息。但是,这整个方法应该有一个超时,如果超时,方法应该中断并返回错误日志。

private Semaphore sem = new Semaphore(0);
private TimeUnit unit = TimeUnit.MILLISECONDS;

public String some_method(Object params, long timeout, TimeUnit unit) {
    long time = 0;
    while(time < timeout) { // not sure about timeout method
        try {
            //some task that is prone to ServerConnectException
            return; // returns value and exits 
        } catch(ServerConnectException ex) {
            sem.acquire();
        } catch(InterruptedException uhoh) {
            System.out.println("uhoh, thread interrupted");
        }
        // increment time somehow
    }
    sem.release();
    return null; // a message of task incompletion
}
  • 我正在考虑运行一个包含信号量的线程,如果出现服务器故障问题会阻塞线程,但我似乎无法组织线程以使其包含信号量但由方法本身包含。

问题: - 但是,该方法已经在一个巨大的类中,并且为该方法创建单独的线程会弄乱整个调用层次结构以及整个 API,所以我不想这样做。我需要一些与 some_method 一起运行的进程,并根据需要在其进程上放置锁定和释放,并带有超时。我应该在想什么?其他一些并发包装器,例如执行器?

谢谢!

【问题讨论】:

  • 我猜你忘了问题
  • 已修复,需要指出来
  • 创建线程实例来调用方法应该不会影响方法本身的设计,因此不会真正影响您的 API。

标签: java multithreading concurrency semaphore


【解决方案1】:

信号量似乎不是在这里使用的正确并发原语,因为您实际上并不需要一个用于锁定的实用程序,而是一个帮助您协调线程间通信的实用程序。

如果您需要传递值流,通常会使用阻塞队列,但如果您需要传递单个值,CountDownLatch 和变量就可以解决问题。例如(未经测试):

  public String requestWithRetry(final Object params, long timeout, TimeUnit unit) throws InterruptedException {
    String[] result = new String[1];
    CountDownLatch latch = new CountDownLatch(1);
    Thread t = new Thread(new Runnable() {
      public void run() {
        while (true) {
          try {
            result[0] = request(params);
            latch.countDown();
            return;
          }
          catch(OtherException oe) {
            // ignore and retry
          }
          catch(InterruptedException ie) {
            // task was cancelled; terminate thread
            return;
          }
        }
      }
    });
    t.start();
    try {
      if (!latch.await(timeout, unit)) {
        t.interrupt(); // cancel the background task if timed out
      }
      // note that this returns null if timed out
      return result[0];
    }
    catch(InterruptedException ie) {
      t.interrupt(); // cancel the background task
      throw ie;
    }
  }

  private String request(Object params) throws OtherException, InterruptedException {
    // should handle interruption to cancel this operation
    return null;
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    相关资源
    最近更新 更多