Java线程池解决单个结果

时间:2012-04-17 07:21:05

标签: java multithreading threadpool

给定一组不相等的输入值(某些输入可能比其他输入更容易解决),如何在找到单个答案时实现多线程方法(在一个基于一个“正确”输入的线程中)

因此,例如,使用多个线程来查找并返回这些数组中的给定字母 (显然在实际程序中有更大的数据集)

Inputs

[A, B, C, D, E, F]
[G, H]
[I, J, K]
[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]

找到目标元素后,需要将其从线程返回到调用函数(父线程),并且可以杀死所有其他线程

我考虑过的事情:

使用线程池('常规'线程,执行器线程)来运行并在调用函数中设置返回值(公共变量?)

阻止主线程的循环障碍,直到找到答案

5 个答案:

答案 0 :(得分:2)

您可以使用其他任务共享和轮询的答案设置AtomicReference,以查看它们是否应该停止。您也可以使用它来通知()等待的线程。

final AtomicReference result = ...
// adds tasks
synchronized(result) {
    while(result.get() == null)
          result.wait();
}

// to check there is no answer. It doesn't have to be synchronized 
// as the value is thread safe.
while(result.get() == null) {


// in the task when a result is found.
synchronized(result) {
    result.set(answer);
    result.notifyAll();
}

我会使用ExecutorService。

答案 1 :(得分:1)

我更喜欢自己做这一切。它提供了更好的机会,但也更灵活。我从控制字段开始:

public volatile boolean  foundIt = false;
public final boolean[]   jobList = { true, true, ..., true };
public final Object      threadLock = new Object();
public final Object      controllerLock = new Object();

(它们不应该是公开的;给它们你可以管理的最小可见性。)然后启动每个线程,让每个线程都知道要搜索哪个数组以及完成时应该关闭哪个布尔值(index,下面)。使用以下命令暂停控制器:

synchronized (controllerLock)  { controllerLock.wait(); }

线程中的Runnable应定期检查foundIt以确保它仍然是假的。如果是,它应该关闭。不需要同步。找到答案时,搜索代码应该执行以下内容:

haveAnswer:  {
    if (foundIt)  break haveAnswer;   // Already found by another thread.
    synchronized (threadLock)  {
        // Only one thread at a time can get into this block.
        if (foundIt)  break haveAnswer;   // Found since previous check.
        foundIt = true;
    }
    // Add code here to put answer in right place.
    // Only one thread will get this far.
}

关闭时,无论是点击搜索数组的末尾,注意foundIt是否为真,或找到答案,都要完成:

synchronized (controllerLock)  {
    jobList[index] = false;    // Tell world this thread is done.
    for (boolean active : jobList)
        if (active)
            // Another thread is still running.
            return;
    // This was the last thread. We're done. Restart controller.
    controllerLock.notifyAll();
}

答案 2 :(得分:0)

在工作线程中添加对控制器的引用(保留所有线程的列表)。

控制器有一个方法来表示已找到结果,该方法存储结果并杀死/中断所有线程。

答案 3 :(得分:0)

不知何故,正在寻找结果的线程需要检查结果是否已找到。他们可以通过中断然后检查中断的标志来执行此操作(抛出InyerruptedExceprion的任何方法都会执行此检查。

他们还可以通过查看其他状态(如结果队列或条件变量)进行检查。

例如:

while (resultQueue.isEmpty()) {
    do a small amount of work
}

检查中断状态:

while (!Thread.interrupted()) {
    do a small amount of work
}

答案 4 :(得分:0)

您可以使用ExecutorCompletionService处理找到的结果。 获得所需结果后,取消剩余的任务。

我喜欢这种方法的是任务仍然很简单。他们只需知道如何完成工作并检测他们何时被取消。

然后,任务的创建者处理处理结果并确定何时取消剩余的工作。