简体   繁体   English

使用期货地图,如何在其中通知()一个元素?

[英]Using Map of Futures, how do I notify() a single element within?

I'm attempting to hold a static list of Futures, and at a later time either cancel() or notify() the Futures which are in progress. 我试图持有一份期货的静态列表,并在以后的某个时间取消()或notify()正在进行的期货。 The Callable class which is associated with these Futures has a wait() within it, so each one must be notified by an outside source to continue. 与这些Future关联的Callable类内部具有一个wait(),因此每个外部类都必须通知其继续。 However, my calls to notify() appear to be ignored, as the callables never get past their wait statement. 但是,我对notify()的调用似乎被忽略了,因为可调用对象永远不会超过其wait语句。 The class with the list of Futures looks something like this: 带有期货列表的类如下所示:

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!
                }
            }
        }
    }

}

The Callable class is just a mockup for now, looks similar to this: 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;
}

The notify() method is called, but seems to have no effect. notify()方法被调用,但似乎没有效果。 The object reference for the Future appears valid (ie the local variable "future" matches the reference of the future stored in the static list). Future的对象引用似乎有效(即,局部变量“ future”与存储在静态列表中的Future的引用匹配)。

I'm probably missing some basic concept of concurrency here, but I expected that when condition2 is met, my Callable would proceed past the wait() call. 我可能在这里缺少并发性的一些基本概念,但是我希望当满足condition2时,我的Callable可以继续进行wait()调用。

Note that if I use cancel() instead of notify(), it interrupts my runnable and causes an InterruptedException as I would expect. 请注意,如果我使用cancel()而不是notify(),它会中断我的可运行程序并引起InterruptedException,这与我期望的一样。

You need to notify the exact same object. 您需要notify 完全相同的对象。 In your case you are notifying on the Future object but waiting on the MyCallable object. 在您的情况下,您正在通知Future对象,但正在等待MyCallable对象。 Unfortunately, I don't know of any easy way for your MyCallable object to see its wrapped Future so there is no wait for it to wait() on it. 不幸的是,我不知道让MyCallable对象看到其包装的Future的任何简便方法,因此不必等待它在其上进行wait()

One solution would be to pass in a lock object into your MyCallable constructor and then save it along with the associated Future . 一种解决方案是将一个锁对象传递到MyCallable构造函数中,然后将其与关联的Future一起保存。 Something like: 就像是:

  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;
         ...
     }
  }

What you seem to be trying to achieve (though I may be wrong) is something like a SettableFuture . 您似乎想要实现的目标(尽管我可能错了)类似于SettableFuture

Not sure if you need the computation ability of a Callable into an Executor, but the SettableFuture should be as easy as creating it and setting when you are ready while the other threads sit's there and waits for another thread to set. 不知道您是否需要执行器中的Callable的计算能力,但是SettableFuture应该像创建它并在其他线程坐在那里等待另一线程设置的准备就绪时一样容易地进行设置。

There seems to be two routes you are approaching the problem. 您要解决此问题似乎有两条路线。

One is with an Executor. 一个是与执行者一起。

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

Thread 1: 线程1:

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

Thread 2: 线程2:

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

The other case is with a SettableFuture 另一种情况是使用SettableFuture

final SettableFuture f = new SettableFuture();

Thread 1: 线程1:

f.set(new Object());

Thread 2: 线程2:

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

Both would achieve the same type of waiting mechanics the differences are that Thread 1 in the first example will submit to a separate thread to create the object. 两者都将实现相同类型的等待机制,不同之处在于第一个示例中的线程1将提交到单独的线程来创建对象。 Thread 2 will still wait until the other thread has completed the operation. 线程2仍将等待,直到另一个线程完成了该操作。 The second example will have thread 2 waiting until thread 1 completes and set's the Future. 第二个示例将让线程2等待线程1完成并设置Future。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用ResourceHandlerRegistry和Spring MVC映射单个文件? - How do I map a single file using ResourceHandlerRegistry and Spring MVC? Java执行程序:如何在执行程序中通知单个等待线程? - Java executors: How to notify a single waiting thread within the executer? 在Tomcat中使用ExecutorService / Futures? - Using ExecutorService / Futures within Tomcat? Java:I=如何在单个元素中使用 ArrayList.contain() - Java: I=How to use ArrayList.contain() within a single element 如何使用一个单独的routebuilder映射2个经过不同编组和解组的服务? - How do I map 2 services that are marshalled and unmarshalled differently using one single routebuilder? 如何使用 Spring JPA/Hibernate 将 SINGLE 表查询的 1 列映射到 COLLECTION - How do I map 1 column of a SINGLE table query to a COLLECTION using Spring JPA/Hibernate 如何实现线程等待通知? - How do I implement thread wait notify? 我如何使用对象内的映射从java中直观地获取键/值 - how do I get key/value in sightly from java using a map within objects 使用Mockito,如何在when子句中检查映射的键值对 - Using Mockito, how do I check for a key-value pair of a map within when clause 如何通知事件的类组件? - How do I notify a class component of an event?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM