给定一组不相等的输入值(某些输入可能比其他输入更容易解决),如何在找到单个答案时实现多线程方法(在一个基于一个“正确”输入的线程中)
因此,例如,使用多个线程来查找并返回这些数组中的给定字母 (显然在实际程序中有更大的数据集)
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]
找到目标元素后,需要将其从线程返回到调用函数(父线程),并且可以杀死所有其他线程
我考虑过的事情:
使用线程池('常规'线程,执行器线程)来运行并在调用函数中设置返回值(公共变量?)
阻止主线程的循环障碍,直到找到答案
答案 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处理找到的结果。 获得所需结果后,取消剩余的任务。
我喜欢这种方法的是任务仍然很简单。他们只需知道如何完成工作并检测他们何时被取消。
然后,任务的创建者处理处理结果并确定何时取消剩余的工作。