我已经编写了线程分解的程序。除了结果之外,测试对每种方法都有效。据我了解,我包括抛出异常的线程,但不包括完成的线程。 这是我得到的描述提示:
Thread newThread (Runnable runnable) - 创建并注册一个新线程。线程的名称应该是“-worker-n”,其中n是线程的编号。 ThreadUnion 必须监视创建的线程的执行 - 请参阅 results() 方法。
List results() - 返回已完成线程的结果列表。对于尚未完成的线程,不得返回任何结果。结果必须包含线程名称、完成执行时的时间戳以及抛出的 Throwable
我得到另一个提示,我应该使用 catch-finally 和 Runnable r 作为参数传递给 newThread,但不知道如何实现它。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadUnionImpl implements ThreadUnion{
private final String name;
private final AtomicInteger threadCount = new AtomicInteger(0);
private final List<FinishedThreadResult> threadList = Collections.synchronizedList(new ArrayList<>());
private boolean shutdownRequested = false;
public ThreadUnionImpl(String name) {
this.name = name;
}
@Override
public int totalSize() {
return threadCount.get();
}
@Override
public int activeSize() {
return (int)Thread.getAllStackTraces().keySet().stream()
.filter(thread -> thread.getName().startsWith(name + "-worker-"))
.count();
}
@Override
public void shutdown() {
shutdownRequested = true;
Thread.getAllStackTraces().keySet().stream()
.filter(thread -> thread.getName().startsWith(name + "-worker-"))
.forEach(Thread::interrupt);
Thread.getAllStackTraces().keySet().stream()
.filter(thread -> thread.getName().startsWith(name + "-worker-"))
.forEach(Thread::interrupt);
}
@Override
public boolean isShutdown() {
return shutdownRequested;
}
@Override
public void awaitTermination() {
Thread.getAllStackTraces().keySet().stream()
.filter(thread -> thread.getName().startsWith(name + "-worker-"))
.forEach(thread -> {
try {
thread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
@Override
public boolean isFinished() {
return shutdownRequested && activeSize() == 0;
}
@Override
public List<FinishedThreadResult> results() {
return threadList;
}
@Override
public Thread newThread(Runnable r) {
if (shutdownRequested) throw new IllegalStateException();
String threadName = this.name + "-worker-" + threadCount.getAndIncrement();
Thread thread = new Thread(r, threadName);
thread.setUncaughtExceptionHandler((t, e) -> {
threadList.add(new FinishedThreadResult(t.getName(), e));
});
return thread;
}
}
一个测试失败,提供响应:
org.opentest4j.AssertionFailedError:
预计:7 实际:4
为了确保在 results() 方法中包含已完成的线程,同时排除仍处于活动状态的线程,您需要更新您的实现。关键是跟踪已完成执行的线程并在调用 results() 方法时检索其结果。
您可以通过更新 newThread() 方法来实现此目的,以使用自定义 Runnable 实现来包装提供的 Runnable,该实现捕获异常并在完成时存储结果。