所以,我有2个Java类。我们称之为 FirstClass 和 SecondClass (实现Runnable)。在 FirstClass 中,我正在做一些事情,然后我创建了4个线程。
Thread t1 = new Thread (new SecondClass(s1));
Thread t2 = new Thread (new SecondClass(s2));
Thread t3 = new Thread (new SecondClass(s3));
Thread t4 = new Thread (new SecondClass(s4));
s1 , s2 , s3 和 s4 都是 String 类型并持有个人价值观。
然后我马上启动线程。
t1.start();
t2.start();
t3.start();
t4.start();
然后在我的 SecondClass 中,我在默认构造函数中接受这些字符串,如下所示
HashMap<String, Integer> map;
public SearchResults(String s) {
map.put(s, 0);
}
在run()方法中我正在执行以下操作
public void run() {
try {
System.out.println(map);
} catch (Exception e) {
// TODO: handle exception
}
}
因此,这个无用程序的结果是 map 打印出4次,有4个不同的值。
我想知道如何返回一个地图的实例,其中包含 t1 的所有值以及 t2 投入等等等。他们都在使用相同的变量 map ,但是每个线程看起来都是自己的事情。
我可以,让线程执行,然后当它们全部完成时,将地图返回到另一个类或其他什么东西?我真的不太了解Threads,所以这让我很困惑。任何帮助将不胜感激。
答案 0 :(得分:3)
有很多方法可以做到这一点。更好的解决方案是切换并使用ExecutorService
而不是自己分叉线程。然后,您可以在Callable<Map>
中实施Runnable
(而不是SecondClass
)并返回每个作业创建的地图。
类似的东西:
// create a thread pool with as many workers as there are jobs
ExecutorService threadPool = Executors.newCachedThreadPool();
List<Future<Map<String, Integer>>> futures =
new ArrayList<Future<Map<String, Integer>>>();
futures.add(threadPool.submit(new SecondClass(s1)));
futures.add(threadPool.submit(new SecondClass(s2)));
futures.add(threadPool.submit(new SecondClass(s3)));
futures.add(threadPool.submit(new SecondClass(s4)));
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
...
Map<String, Integer> all = new HashMap<String, Integer>();
for (Future<Map<String, Integer>> future : futures) {
// future.get() throws an exception if your call method throws
all.putAll(future.get());
}
然后,您的SecondClass
实施Callable
:
public Map<String, Integer> call() {
...
return map;
}
您可以使用的其他一些机制包括:
ConcurrentHashMap
(不太好)的共享static
BlockingQueue
上显示结果Map
的类上调用方法。答案 1 :(得分:2)
您可以将地图设为 static :
private static Map<String, Integer> map = new HashMap<String, Integer>();
这将使您的所有SecondClass
实例共享相同的地图。
如果您这样做,请不要忘记正确同步,方法是更改为其他Map
类型或同步您的写入。您可以阅读该主题here, in the Java Tutorials。
答案 2 :(得分:0)
您想要的是使用Future
和ExecutorService
。
看看它的javadoc,但是用它可以计算异步并等待Future#get()
的结果。最后,您可以将它们一起打印出来。
类似的东西:
public class SearchResults implements Callable {
//
}
...
ExecutorService executor = Executors.newFixedThreadPool(4);
List<SearchResults> searchResults = new LinkedList<SearchResults>();
List<Future> results = executor.invokeAll(searchResults);
Map<String, Integer> calculatedResults = new HashMap<String, Integer>();
for (Future result : results) {
calculatedResults.putAll(result.get());
}
// print calculated results
答案 3 :(得分:0)
如果您希望在运行所有线程结束时获得结果,则可能需要查看使用CyclicBarrier
或CountdownLatch
。
答案 4 :(得分:0)
正如其他人所说,您可以使用ConcurrentHashMap
或ThreadLocal
变量,使用它可以在多个线程中共享变量。
现在进入问题的第二部分,即
我可以,让线程执行,然后它们全部执行 完成后,将地图返回到另一个类或什么?
您可以像已经建议的那样使用Future
,但在这种情况下,您还必须等待,如果执行尚未完成,您将如何处理不同线程的竞争并通知另一个线程事情。如果您的要求如此,您可以继续这样做。
但我建议你经历一次Observer
模式,并检查一下是否可以帮助你满足你的要求。一个类可以观察线程,一旦完成就可以通知。如果有任何问题让我们知道,请尝试实施它。