0

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

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

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]

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

我考虑过的事情:

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

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

4

5 回答 5

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。

于 2012-04-17T07:28:27.670 回答
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();
}
于 2012-04-17T17:04:36.837 回答
0

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

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

于 2012-04-17T07:24:28.280 回答
0

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

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

例如:

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

检查中断状态:

while (!Thread.interrupted()) {
    do a small amount of work
}
于 2012-04-17T07:28:21.030 回答
0

您可以使用 ExecutorCompletionService 来处理找到的结果。一旦你得到你想要的结果,取消剩余的任务。

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

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

于 2012-04-17T15:58:59.137 回答