我有一个多线程批处理应用程序,可以在5到10个并发执行线程之间运行。他们的数据段经过精心切片,尽可能均匀分布,但当然,执行时间总是不同的。我想做的是在最后一个线程完成时调用最后一种onFinalize方法,这将进行一些统计计算。
我想知道一个线程知道它是最后一个(而不是查询DB,这似乎是行人)的最佳方法是有一个静态var,当一个同步块时会增加一个静态var。每个线程完成时添加和减少新线程。因此,当一个线程完成并减少它时,我可以有一个if来查看未完成的线程数是否为0然后调用最终的统计数据。
这就是我的想法。我想知道是否有更好,更优雅或防弹的方式来实现这一目标。
使用Java 7
由于
答案 0 :(得分:0)
为什么不在最后的每个线程上调用Thread.join()?你可以有一个for循环来调用它们 - 它会在第一次运行时锁定,然后当它完成时,返回然后你锁定下一次运行。当你退出循环时,他们都退出了。
public class ThreadManager {
private List<Thread> threads;
public void addThread(Thread thread) {
threads.add(thread);
}
public void waitTillAllComplete() {
for (int ind=0; ind<threads.size(); ind++)
threads.get(ind).join();
}
}
答案 1 :(得分:0)
我通过创建扩展基本Runnable
接口的框架来提供类似的东西,以提供更强大的线程架构。后来我发现它与GWT中的异步代码非常相似,用于类似目的。
这是来自记忆,但它基本上归结为:
public interface AsyncRunnable<T> extends Runnable
{
AsyncCallback<T> getCallback();
T runAsync();
}
public interface AsyncCallback<T>
{
void onSuccess(T data);
void onFailure(Exception exception);
}
public interface AsyncCallbackInvoker<T> extends Runnable
{
// implies requirement for callback...
AsyncCallback<T> getCallback();
}
public class SuccessfulAsyncCallbackInvoker<T> implements AsyncCallback<T>
{
private final AsyncCallback<T> callback;
private final T data;
public SuccessfulAsyncCallbackInvoker(AsyncCallback<T> callback, T data)
{
// note: data being null may be valid; callback would not be
this.callback = callback;
this.data = data;
}
@Override
public void run()
{
callback.onSuccess(data);
}
@Override
public AsyncCallback<T> getCallback()
{
return callback;
}
}
public class FailureAsyncCallbackInvoker<T> implements AsyncCallback<T>
{
private final AsyncCallback<T> callback;
private final Exception exception;
public FailureAsyncCallbackInvoker(AsyncCallback<T> callback, Exception exception)
{
// note: data being null may be valid; callback would not be
this.callback = callback;
this.exception= exception;
}
@Override
public void run()
{
callback.onFailure(exception);
}
@Override
public AsyncCallback<T> getCallback()
{
return callback;
}
}
public abstract class AbstractAsyncRunnable<T> implements AsyncRunnable<T>
{
private final AsyncCallback<T> callback;
public AbstractAsyncRunnable(AsyncCallback<T> callback)
{
// if == null -> throw
this.callback = callback;
}
@Override
public /* final */ void run()
{
AsyncCallbackInvoker<T> invoker;
try
{
T data = runAsync();
invoker = new SuccessfulAsyncCallbackInvoker<T>(callback, data);
}
catch (Exception e)
{
invoker = new FailureAsyncCallbackInvoker<T>(callback, e);
}
invokeCallback(invoker);
}
// allows overriding to put callback on whatever Thread you want
protected void invokeCallback(AsyncCallbackInvoker<T> invoker)
{
invoker.run();
}
}
实际上,它已被证明非常强大,特别是通过提供覆盖invokeCallback
的能力,我们可以利用大量线程安全操作并保证响应。
在实践中,实现只需要覆盖runAsync
的{{1}}方法,并提供他们认为合适的AsyncRunnable
个方法。重要的是要注意,有时您真正使用它来简单地标记完成,在这种情况下,AsyncCallback
可以是T
(Void
来自return null
你使用那个)。
答案 2 :(得分:0)
所以你还可以做的是你可以创建一个ThreadManager
类。这个类应该有一个List<Thread>
。每当您创建新的Thread
来执行任务时,您应register
ThreadManager
。然后在ThreadManager
中创建一个方法,该方法返回number
中live Threads
的总List
。
通过这种方式,您可以随时查看正在运行的线程数,还可以根据需要对正在运行的线程执行任何其他操作。还应该定期运行一个Thread
,这应该清除List
中所有死亡的线程引用。
示例ThreadManager
可能如下所示:
public class ThreadManager {
private static ThreadManager tm;
private List<Thread> threads;
public static ThreadManager get() {
if(null == tm) {
tm = new ThreadManager();
}
return tm;
}
private ThreadManager() {
threads = new ArrayList<Thread>();
}
public int getCountOfAliveThreads() {
int count = 0;
for(Thread t : threads) {
if(t.isAlive()) {
count++;
}
}
return count;
}
}
希望这会有所帮助。您可以在Thread List
上执行其他功能。
答案 3 :(得分:-1)
我很欣赏所有超级有用和启发性的答案,然而,带静态和易失性的简单计数器似乎工作正常:
private static volatile int crntThrdCnt = 0;
然后
@Override
public void run()
{
crntThrdCnt++;
this.runBatchInstance();
crntThrdCnt--;
if(crntThrdCnt == 0)
{
ProcessManager prcsMgr = new ProcessManager();
Batch batch = prcsMgr.getBatch(this.batchID);
batch.setEndTime(new Date());
prcsMgr.updateBatch(batch);
}
}