当前位置: 首页 > 知识库问答 >
问题:

使用Map of Futures,如何通知()其中的单个元素?

麹权
2023-03-14

我正在尝试保存一个静态的Futures列表,稍后取消()或通知()正在进行的Futures。与这些Futures关联的Callable类在其中有一个等待(),因此每个都必须由外部来源通知才能继续。但是,我对通知()的调用似乎被忽略了,因为可调用对象永远不会超过它们的等待语句。具有Futures列表的类如下所示:

private static Map <String, Future<Object>> results = new HashMap <String, Future<Object>>();

ExecutorService taskExecutor;

public void doStuff() {
    taskExecutor = Executors.newCachedThreadPool();

    // loop inifinitely - external processes will modify the conditions within
    while(!shutItDown) {

        if (<condition1>) {
            // condition 1 dictates the kick-off of a new callable
            Future<Object> future = taskExecutor.submit(new MyCallable(id));
            results.put(id, future);
        }
        else if (<condition2>) {
            // condition 2 represents a callable in a wait status needs
            // to be notified
            Future<Object> future = results.get(uid);
            if (future != null) {
                synchronized(future) {
                    future.notify();  // this doesn't have the desired effect!
                }
            }
        }
    }

}

Callable类目前只是一个模型,看起来像这样:

public class MyCallable implements Callable<Object> {

private String id;

public MyCallable(String id) {
    this.id = id;
}

@Override
public Object call() throws Exception {     

    try {

        // do some work here, then wait on outside notification

        synchronized(this) {
            this.wait();  // never gets past here!!!
        }

        // do some other work here, once this has been notified
    } 
    catch (InterruptedException e) {
        e.printStackTrace();
    }

    return null;
}

调用 notify() 方法,但似乎没有效果。Future 的对象引用看起来有效(即局部变量“future”与静态列表中存储的未来的引用相匹配)。

我在这里可能缺少一些并发的基本概念,但我预计当满足条件2时,我的Callable将继续通过wait()调用。

请注意,如果我使用取消()而不是通知(),它会中断我的可运行程序并导致我所期望的InterruptedException。

共有2个答案

段渊
2023-03-14

你似乎想要实现的(尽管我可能错了)是一个可设定的未来。

不确定您是否需要调用到执行器中的计算能力,但是SettableFuture应该像创建它一样简单,并在其他线程坐在那里并等待另一个线程设置时设置它并设置。

似乎有两条路线正在解决问题。

一个是与遗嘱执行人。

Executor e = Executors.newSingleThreadExecutor();
Future f = null;

线程1:

f = e.submit(new Callable(){
  public Object call(){
    return new Object();
  }
});

线程2:

f.get(); //will suspend Thread 2 until the Executor submits the callable

另一种情况是具有可设定的未来

final SettableFuture f = new SettableFuture();

线程1:

f.set(new Object());

线程 2:

f.get(); //will suspend Thread 2 until Thread 1 set's the Future.

两者都将实现相同类型的等待机制,不同之处在于第一个示例中的线程1将提交给一个单独的线程来创建对象。线程2仍将等待,直到另一个线程完成操作。第二个示例将让线程2等待,直到线程1完成并设置未来。

应煌
2023-03-14

您需要通知完全相同的对象。在您的情况下,您正在通知Future对象,但在等待MyCallable对象。不幸的是,我不知道您的MyCallable对象有什么简单的方法可以查看其包装的Future,因此无需等待它等待()

一种解决方案是将锁定对象传入 MyCallable 构造函数,然后将其与关联的 Future 一起保存。像这样:

  private static Map <String, FutureLock> results =
        new HashMap <String, FutureLock>();
  ...
  Object lock = new Object();
  Future<Object> future = taskExecutor.submit(new MyCallable(id, lock));
  results.put(id, new FutureLock(future, lock));
  ...

  public class FutureLock {
      private Future<Object> future;
      private Object lock;
      public FutureLock(Future<Object> future, Object lock) {
         this.future = future;
         this.lock = lock;
      }
      public void notify() {
         synchronized (lock) {
            lock.notify();
         }
      }
      public Object get() throws Exception {
         return future.get();
      }
  }

  public class MyCallable {
     private Object lock;
     public MyCallable(String id, Object lock) {
         this.lock = lock;
         ...
     }
  }
 类似资料:
  • 问题内容: 我的页面上有一个canvas元素,我想单击此画布中的特定(x,y)坐标。我使用watir-webdriver: 但是此代码仅单击画布的中心,而不单击指定的(x,y)坐标。怎么了 UPD:所以现在我使用以下代码: 但是它仍然单击画布的中心,而不单击指定的(x,y)坐标…有什么想法吗? UPD 2:这仅是FIREFOX问题(在Chrome中运行良好) 问题答案: 运动 移动到指定元素的中心

  • 我有一个使用Xamarin.Forms的应用程序,针对IOS,Android和WP 8。 我的应用中需要推送通知功能。 我看过<code>pushsharp</code>演示,它似乎很有前途。但我看到的所有代码都是针对每个平台分别编写的。 我希望这件事能在法庭上进行。Forms项目,在App.cs中的某个地方,这样我就不需要重复注册设备的代码,也不需要处理应该如何处理推送通知。 任何帮助都将不胜感

  • 用于删除邮件 这是有效的,但当应用程序关闭时,代码不起作用。我们能从服务器端有效负载通知或附加标记和id吗

  • 我知道有很多关于这个话题的文章,但我就是找不到正确的答案。 有没有办法知道用户何时收到远程通知以及用户何时在iOS8上点击了一个。我想知道这一点,因为当我收到它时,我想保存它,当用户点击它时,我想打开一些视图。 我找到了这个答案https://stackoverflow.com/a/16393957/1241217但问题是,当用户在应用程序中打开通知中心并单击其中一个时,该应用程序既不处于非活动状

  • 问题内容: 我有以下HTML: 我下面的单击“ Google搜索”按钮的代码在WebDriver中使用Java时效果很好。 我想将JavaScript与WebDriver一起使用以单击按钮。我该怎么做? 问题答案: 通过JavaScript执行点击具有一些您应该注意的行为。例如,如果绑定到元素事件的代码调用,则可能会发现Selenium代码挂起,具体取决于浏览器驱动程序的实现。也就是说,您可以使用

  • 所以在Android开发者文档中(https://developer.android.com/training/notify-user/build-notification)它给出了创建通知通道的命令行: 但复制了准确的代码块后,我得到了错误: 我认为这是一个方法,但不是从它的类(上下文)中调用的?但为什么会出现在文档中?我应该换成什么?