如何让runnable实例在一个线程中等待并通过一些其他线程通知?

时间:2017-03-18 15:44:30

标签: java multithreading concurrency core java.util.concurrent

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

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");

        }

    }

}

3 个答案:

答案 0 :(得分:1)

  

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

不要notify()个帖子。通知对象。 &#34;守卫区块&#34; Java Concurrency教程的一节解释了如何使用wait()notify()https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

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

答案 1 :(得分:0)

  

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

您正在使用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();
}

答案 2 :(得分:0)

@Gray是对的,但最好使用completionService而不是直接检索期货,以便最大限度地减少等待。 CompletionService允许您在将来的对象可用时从未来获取值。