繁体   English   中英

如何使可运行实例在一个线程中等待并由其他线程通知?

[英]how to make runnable instance to wait in one thread and notify by some othrer threads?

在下面的代码中,一个可运行实例正在等待获取通知。 如果我使用方法或一个包含要通知的线程的其他类,如何通过其他线程通知此线程。我被困在这里,请帮助...

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.cgi.sample.jms.requestor.RequestorApplication.Runner;

public class RequestorApplication {

    public static String correlationId;

    static ArrayList<Runner> list = new ArrayList<Runner>();

    static Map<Long, Runner> map = new HashMap<Long, Runner>();

    static Runner runner;


    public static void main(String args[]) throws Exception {

        RequestorApplication application = new RequestorApplication();

        application.waiter(map);

        System.out.println("All the threads are started");
    }

    public void waiter(Map<Long, Runner> map) {

        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 2; i++) {

            Runner instance = new Runner();

            System.out.println("Executing thread " + " with " + Thread.currentThread().getName());

            long threadId = Thread.currentThread().getId();

            String threadname = Thread.currentThread().getName();

            executor.execute(instance);

            RequestorApplication.runner = instance;

            synchronized (RequestorApplication.runner) {

                map.put(threadId, RequestorApplication.runner);



                try {
                    RequestorApplication.runner.wait();
                    // notifier(map);
                    System.out.println(threadname + "  Thread entered into waiting state!!!");
                    // Thread.currentThread().wait();
                    System.out.println(threadname + "  Thread woke up from wait!!!!!");

                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
            }
        }

    }

    public void notifier(Map<Long, Runner> map) {
        synchronized (RequestorApplication.runner) {

            for (Map.Entry<Long, Runner> entry : map.entrySet()) {

                System.out.println("stored threads in map are--->" + map.get(entry.getKey()));

                entry.getValue().notify();
            }

        }

    }

    class Runner implements Runnable {
        public void run() {
            System.out.println("runner invoked");

        }

    }

}

我应该使用包含线程通知的方法还是一个以上的类?

不要notify()线程。 通知对象 Java Concurrency教程的“ Guarded Blocks”部分说明如何使用wait()notify() https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html


通常,您应该完全避免使用wait()notify() 它们是低级原语,旨在用于实现高级同步对象。 java.util.concurent软件包已经具有许多可以使用的更高级别的对象。 这意味着您可以减少编写正确代码的工作,也可以减少需要了解您的代码的其他人的工作。

在下面的代码中,一个可运行实例正在等待获取通知...

您正在使用ExecutorService线程池,但完全缺少它的重要功能之一。 将作业添加到线程池时,请使用submit(...)方法,该方法返回Future对象。 然后,您可以调用future.get()以等待作业完成并返回值。 您永远不需要自己等待,等等。

Future<Void> future = executor.submit(instance);
// now we wait for the thread to complete
future.get();

另外,尽管它可以工作,但是直接调用Thread.wait()被认为是非常糟糕的形式。 碰巧在线程完成时会调用notify() ,但这是应该依靠的实现细节。 使用Thread加入或使用上面的Future.get() 另外,如果线程调用wait() 之前返回,则可能会错过notify()并且代码将永远不会返回。

最后,正如@ vijayraj34指出的那样,您的代码现在是单线程的,因为您提交了每个作业,然后立即等待它。 您应该做的是派生所有线程并将Future对象保存在集合中。 然后,一旦开始工作,您就可以依次等待每个Future

就像是:

List<Future<Void>> futures = new ArrayList<>();
for (int i = 0; i < 2; i++) {
   Runner instance = new Runner();
   // save the futures for later
   futures.add(executor.submit(instance));
}
// after we submit all of our jobs we shutdown the thread-pool
executor.shutdown();
...
// now we go back and wait for all of the runners that have been working in the background
for (Future<Void> future : futures) {
   future.get();
}

@Gray是正确的,但是最好使用completionService而不是直接检索期货,这样可以最大程度地减少等待时间。 当将来的对象可用时,CompletionService允许您从将来获得价值。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM