Java:如何获得具有特定条件的最快任务的返回值?

时间:2018-04-27 01:42:28

标签: java multithreading

我有三节课,让我们说A,B和C.

他们每个人都使用不同的算法。

在我的主类Main中,我希望有一个像" search(String toSearch)"这样的方法。该方法使用类A,B和C.

我希望每个任务(A,B,C)都有自己的线程,我的方法"搜索" 返回"最快的任务" (具有特定条件,返回值为NOT NULL)。如果可能的话,其他任务应立即死亡(因为不再需要它们)。

提前致谢。

我想要做的例子:

public static String search(String toSearch) {
    String aResult = A.search(toSearch);
    String bResult = B.search(toSearch);
    String cResult = C.search(toSearch);
    // aResult, bResult & cResult should start at the same time and the first one with a result (NOT NULL) is the "winner"
// if any of them is NULL (or empty), then we'll return NULL
    // return the first result that is NOT NULL and let the others die if they are still searching
}

3 个答案:

答案 0 :(得分:0)

分析您的代码。 如果存在,String aResult = A.search(toSearch);中的结果意味着阻塞。因此,在aResult收到结果之前,其他语句将无效。

如果A.search,B.search和C.search是并发的,那么您的代码应该是:

public static String search(String toSearch) {
    //
    A.search(toSearch, observer);
    B.search(toSearch, observer);
    C.search(toSearch, observer);
    //
    return observer.get()//blocked until an result NOT NULL
}

观察者是这样的:

public class Observer {
    private Object value;

    public void set(Object value){
        if (value != null) {
          syncronized(this){
            this.value = value;
            this.notify();
          }
        }
    }    

    public Object get(){
        syncronized(this){
           this.wait()
        }
        return value;
   }
}

答案 1 :(得分:0)

我认为您可能正在寻找Java的ExecutorCompletionService:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorCompletionService.html

答案 2 :(得分:0)

将3个任务(A,B,C)提交给具有至少3个线程的执行程序服务,应该并行运行它们。

每项任务都应该做两件事,通知并检查是否应该停止。

示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FastestOf3 {

    public static void main(String[] args) throws Exception {
        System.out.println(search("foo"));
    }

    static Object search(String key) throws InterruptedException {
        ExecutorService es = Executors.newFixedThreadPool(3);
        final Object[] answer = new Object[1];
        Future f1 = es.submit(() -> searchEmulation(answer, 1000, "1"));
        Future f2 = es.submit(() -> searchEmulation(answer, 200, "2"));
        Future f3 = es.submit(() -> searchEmulation(answer, 500, "3"));
        synchronized(answer) {
            while(! (f1.isDone() && f2.isDone() && f3.isDone()) && answer[0]==null) {
                answer.wait();
            }
            es.shutdownNow();
        }
        return answer[0];

    }

    static void searchEmulation(Object[] mailbox, int delay, Object answer) {
        //some work...
        if(Thread.currentThread().isInterrupted())
            return;
        //some more work...
        if(Thread.currentThread().isInterrupted())
            return;
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            //e.printStackTrace();
            return;
        }
        //some more work...
        synchronized(mailbox) {
            if(mailbox[0]==null)
                mailbox[0] = answer;
            mailbox.notify(); //notify even if no result, to wake main thread to check.
        }

    }

}