本文介绍了在Java中安排例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个需要从给定的URL下载文件的任务,其中一个要求是可以处理网络故障和异常。



在我的实现中有一个DonwloadManager为每个URL分配一个线程,以免阻塞。



问题是我不知道如何通过代码模拟故障和异常,我尝试使用Quartz作为调度程序和一个仅抛出异常的作业,但据我所知,调度程序运行在不同的线程上,所以这不会影响下载线程。



有没有办法模拟下载线程中的例外?



以下是我的代码以获得更多见解:

  public class DownloadManager {

intignedMemory = 0;

void validateURLs(String [] urls){
if(urls.length == 0){
throw new IllegalArgumentException(URL 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>();
allocateMemory = memorySize / urls.length;
(String url:urls){
completionService.submit(new DownloadWorker(url,assignedMemory));
}
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实现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状态调用()throws异常{
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(); (int i = 0; i< buffer.limit(); i ++){
outputChannel.write(buffer);

}
buffer.clear();
}
outputChannel.close();
inputChannel.close();
outputFile.close();
return new Status(assignedURL,true);
}

}



关于如何以编程方式模拟/测试异常的任何建议?



更新:我在想,而不是排除异常,更容易模拟未来的状态,所以它将返回一个例外。

解决方案

在您的 DownloadWorker 中, 6秒,当您在 DownloadManager 线程中获取 Future 时,设置 timeout 5秒。现在你将得到超时异常。



这样,列出异常你想抓住 DownloadManager 线程,并将它们从您的 DownloadWorker 中删除​​。



其他方式是按照以下方式执行执行方法之后的 ThredPoolExecutor



请注意, FutureTask 会吞下异常(如果在上使用submit()而不是execute() ExecutorService 。查看源代码,因此从 DownloadWorker 正确地引发异常。


I'm developing a task that requires downloading files from given URLs, one of the requirement is that it could handle network failures and exceptions.

In my implementation I had a DonwloadManager that assigns a thread for every URL, so as not to be blocking.

The problem is that I am not sure how to mock failures and exceptions through the code, I tried using Quartz as scheduler and a job that only throws exception, but as far as I know the scheduler runs on different thread, so this won't affect the downloading thread at all.

Is there a way to mock the exceptions within the downloading thread ?

Here is my code for more insights:

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;
}

And this is the download 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);
}

}

Any suggestions on how to mock/test the exception programmatically ?

Update: I was thinking, instead of scheduling exceptions, it would be easier to mock the resulting Future status, so that it returns an exception.

解决方案

In your DownloadWorker, sleep for 6 seconds and when you are getting a Future in DownloadManager thread, set timeout as 5 seconds. Now you will get timeout exception.

In this way, list out Exceptions you want to catch in DownloadManager thread and throw them from your DownloadWorker.

Other way is overriding ThredPoolExecutor after execute method as per this one:

Handling exceptions from Java ExecutorService tasks

Note that FutureTasks swallows the exceptions (if you use submit() instead of execute() on ExecutorService. Have a look at source code. So raise exceptions properly from DownloadWorker.

这篇关于在Java中安排例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 09:20