我有一个模块,可以在开始时从文件中反序列化一堆资源。每个都花费时间,所以我想以多线程方式实现它,以便每个线程摄取一个资源。根据我在网上找到的一些例子,我编写了这个测试类,它代表了我主模块的资源摄取步骤。
public class MultiThreadedResourceIngest {
private static ResourceClass1 r1 = null;
private static ResourceClass2 r2 = null;
private static ResourceClass3 r3 = null;
static class ResourceReader extends Thread {
private Thread t = null;
private int id = -1;
private String path2read = null;
ResourceReader( final int id, final String path2read){
this.id = id;
this.path2read = path2read;
}
public void run() {
if (path2read != null && path2read.length() > 0)
{
switch (id) {
case 0:
r1 = new ResourceClass1(path2read);
break;
case 1:
r2 = new ResourceClass2(path2read);
break;
case 2:
r3 = new ResourceClass3(path2read);
break;
default:
break;
}
}
log.info(String.format("Thread with id=%d and path=%s exiting", id, path2read));
}
public void start ()
{
if (t == null)
{
t = new Thread (this);
t.start ();
}
}
}
public static void main(String[] args) {
final String[] paths = new String[] {"path1", "path2", "path3"};
log.info("STARTING MTHREADED READ");
ArrayList<ResourceReader> rrs = new ArrayList<ResourceReader>();
for (int i=0; i < paths.length; i++)
{
ResourceReader rr = new ResourceReader(i,paths[i]);
rr.start();
rrs.add(rr);
}
log.info("JOINING");
for (ResourceReader rr: rrs)
{
try {
rr.join();
} catch (InterruptedException e) {
// Thread interrupted
e.printStackTrace();
}
}
// Want to reach this point only when all resources are ingested
//
log.info("MTHREADED FINISHED");
}
}
所以这里我有3个资源,我想在所有线程完成后才到达标记为// Want to reach this point...
的点。这就是为什么我已经实现了join()
循环,除非它没有按预期工作,即日志看起来像这样:
STARTING MTHREADED READ
Thread with id=0 and path=path1 exiting
JOINING
Thread with id=2 and path=path3 exiting
MTHREADED FINISHED
Thread with id=1 and path=path2 exiting
在继续操作之前,我需要更改以等待所有资源被读取?
答案 0 :(得分:2)
您宣布类资源阅读器扩展线程 ,但您创建另一个并在start中启动它:
t = new Thread (this);
t.start ();
您应该加入此主题,而不是
rr.join();
因此,只需删除 ResourceReader 中的 start()方法,一切都会正常工作。
答案 1 :(得分:0)
你覆盖了线程的start方法,它不会调用super.start()。 所有这一切start()都会创建一个新的第二个线程。删除第二个线程,不要覆盖start()。
这样,对rr.start()的调用将真正启动rr线程,它将结束,join()也将结束。
答案 2 :(得分:0)
太复杂了!为什么不这样做?
static class ResourceReader implements Runnable {
...
public void run() {
...
}
}
public static void main(String[] args) {
...
ArrayList<Thread> rrs = new ArrayList<>();
for (int i=0; i < paths.length; i++)
{
Thread rr = new Thread(new ResourceReader(i,paths[i]));
rr.start();
rrs.add(rr);
}
...
for (Thread rr: rrs)
{
try {
rr.join();
} catch (InterruptedException e) {
...
}
}
...
}