在 Java 中安排例外
Schedule exceptions in Java
我正在开发一项需要从给定的 URL 下载文件的任务,其中一个要求是它可以处理网络故障和异常。
在我的实现中,我有一个 DonwloadManager,它为每个 URL 分配一个线程,以免阻塞。
问题是我不确定如何通过代码模拟失败和异常,我尝试使用 Quartz 作为调度程序和一个只抛出异常的作业,但据我所知调度程序在不同的线程上运行,所以这根本不会影响下载线程。
有没有办法模拟下载线程中的异常?
这是我的代码以获得更多见解:
public class DownloadManager {
int allocatedMemory = 0;
void validateURLs(String[] urls) {
if (urls.length == 0) {
throw new IllegalArgumentException("URLs List is empty");
}
}
public ArrayList<Status> downloadURLs(String[] urls, int memorySize) throws Exception {
validateURLs(urls);
ExecutorService executor = Executors.newWorkStealingPool();
CompletionService<Status> completionService = new ExecutorCompletionService<Status>(executor);
ArrayList<Status> downloadStatus = new ArrayList<Status>();
allocatedMemory = memorySize / urls.length;
for (String url : urls) {
completionService.submit(new DownloadWorker(url, allocatedMemory));
}
for(int i=0;i<urls.length;i++){
Future<Status> URLStatus = completionService.take();
System.out.println(URLStatus.get());
downloadStatus.add(URLStatus.get());
}
executor.shutdown();
return downloadStatus;
}
这是下载 Worker:
class DownloadWorker implements Callable<Status> {
static final int SUCCESS = 1, FAILURE = 0;
private int bufferSize;
private String assignedURL;
public DownloadWorker(String assignedURL, int bufferSize) {
this.bufferSize = bufferSize;
this.assignedURL = assignedURL;
}
public Status call() throws Exception {
URLConnection openConnection = new URL(assignedURL).openConnection();
openConnection.addRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/39.0");
String outputFileName = assignedURL.substring(assignedURL.lastIndexOf("/") + 1);
RandomAccessFile outputFile = new RandomAccessFile(outputFileName, "rw");
ReadableByteChannel inputChannel = Channels.newChannel(openConnection.getInputStream());
FileChannel outputChannel = outputFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
while (inputChannel.read(buffer) > 0) {
buffer.flip();
for (int i = 0; i < buffer.limit(); i++) {
outputChannel.write(buffer);
}
buffer.clear();
}
outputChannel.close();
inputChannel.close();
outputFile.close();
return new Status(assignedURL, true);
}
}
关于如何以编程方式 mock/test 异常的任何建议?
更新:我在想,与其安排异常,不如模拟结果 Future 状态更容易,这样它 returns 就会成为异常。
java executors 是另一种选择(参见 ExecutorService)
- 您可以在执行器中使用awaitTermination方法在当前线程中等待所有任务完成
- 检查 Future(提交时返回的元素)是否存在异常
在您的 DownloadWorker
中休眠 6 秒,当您在 DownloadManager
线程中获得 Future
时,将 timeout
设置为 5 秒。现在你会得到 timeout
异常。
这样,列出Exceptions
你想在DownloadManager
线程中捕获并从你的DownloadWorker
中抛出它们。
另一种方法是在执行方法之后覆盖 ThredPoolExecutor
:
Handling exceptions from Java ExecutorService tasks
请注意,FutureTask
s 吞下了异常(如果您在 ExecutorService
上使用 submit() 而不是 execute())。查看源代码 code。因此正确地引发异常来自 DownloadWorker
.
我正在开发一项需要从给定的 URL 下载文件的任务,其中一个要求是它可以处理网络故障和异常。
在我的实现中,我有一个 DonwloadManager,它为每个 URL 分配一个线程,以免阻塞。
问题是我不确定如何通过代码模拟失败和异常,我尝试使用 Quartz 作为调度程序和一个只抛出异常的作业,但据我所知调度程序在不同的线程上运行,所以这根本不会影响下载线程。
有没有办法模拟下载线程中的异常?
这是我的代码以获得更多见解:
public class DownloadManager {
int allocatedMemory = 0;
void validateURLs(String[] urls) {
if (urls.length == 0) {
throw new IllegalArgumentException("URLs List is empty");
}
}
public ArrayList<Status> downloadURLs(String[] urls, int memorySize) throws Exception {
validateURLs(urls);
ExecutorService executor = Executors.newWorkStealingPool();
CompletionService<Status> completionService = new ExecutorCompletionService<Status>(executor);
ArrayList<Status> downloadStatus = new ArrayList<Status>();
allocatedMemory = memorySize / urls.length;
for (String url : urls) {
completionService.submit(new DownloadWorker(url, allocatedMemory));
}
for(int i=0;i<urls.length;i++){
Future<Status> URLStatus = completionService.take();
System.out.println(URLStatus.get());
downloadStatus.add(URLStatus.get());
}
executor.shutdown();
return downloadStatus;
}
这是下载 Worker:
class DownloadWorker implements Callable<Status> {
static final int SUCCESS = 1, FAILURE = 0;
private int bufferSize;
private String assignedURL;
public DownloadWorker(String assignedURL, int bufferSize) {
this.bufferSize = bufferSize;
this.assignedURL = assignedURL;
}
public Status call() throws Exception {
URLConnection openConnection = new URL(assignedURL).openConnection();
openConnection.addRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/39.0");
String outputFileName = assignedURL.substring(assignedURL.lastIndexOf("/") + 1);
RandomAccessFile outputFile = new RandomAccessFile(outputFileName, "rw");
ReadableByteChannel inputChannel = Channels.newChannel(openConnection.getInputStream());
FileChannel outputChannel = outputFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
while (inputChannel.read(buffer) > 0) {
buffer.flip();
for (int i = 0; i < buffer.limit(); i++) {
outputChannel.write(buffer);
}
buffer.clear();
}
outputChannel.close();
inputChannel.close();
outputFile.close();
return new Status(assignedURL, true);
}
}
关于如何以编程方式 mock/test 异常的任何建议?
更新:我在想,与其安排异常,不如模拟结果 Future 状态更容易,这样它 returns 就会成为异常。
java executors 是另一种选择(参见 ExecutorService)
- 您可以在执行器中使用awaitTermination方法在当前线程中等待所有任务完成
- 检查 Future(提交时返回的元素)是否存在异常
在您的 DownloadWorker
中休眠 6 秒,当您在 DownloadManager
线程中获得 Future
时,将 timeout
设置为 5 秒。现在你会得到 timeout
异常。
这样,列出Exceptions
你想在DownloadManager
线程中捕获并从你的DownloadWorker
中抛出它们。
另一种方法是在执行方法之后覆盖 ThredPoolExecutor
:
Handling exceptions from Java ExecutorService tasks
请注意,FutureTask
s 吞下了异常(如果您在 ExecutorService
上使用 submit() 而不是 execute())。查看源代码 code。因此正确地引发异常来自 DownloadWorker
.