我正在开发一项需要从给定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;
}
这是下载工作者:
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);
}
}
有关如何以编程方式模拟/测试异常的任何建议吗?
更新:我在想,不是调度异常,而是模拟生成的Future状态会更容易,因此它会返回异常。
答案 0 :(得分:0)
java executors是另一种选择(参见ExecutorService)
答案 1 :(得分:0)
在DownloadWorker
中,睡眠6秒,当您在Future
主题中获得DownloadManager
时,请将timeout
设置为5秒。现在您将获得timeout
例外。
通过这种方式,列出要Exceptions
个帖子中的DownloadManager
,并将其从DownloadWorker
中删除。
其他方法是在执行方法之后覆盖ThredPoolExecutor
:
Handling exceptions from Java ExecutorService tasks
请注意,FutureTask
会吞下异常(如果您在ExecutorService
上使用submit()而不是execute()。请查看来源code。因此,从{{0}}正确引发异常{1}}。