0

我很难以我希望的方式正确地对我的应用程序进行编程。

目前,我的应用程序(作为 Java Servlet)将查询数据库以获取要处理的项目列表。对于列表中的每个项目,它将提交一个 HTTP Post 请求。我正在尝试创建一种方法,如果用户请求,我可以停止此处理(甚至终止正在进行的 HTTP Post 请求)。可以有同时处理不同查询的线程。现在,我将停止所有线程中的处理。

我当前的尝试涉及在 Callable 类中实现数据库查询和 HTTP Post。然后我通过 Executor Service 提交 Callable 类以获取 Future 对象。

但是,为了正确停止处理,我需要中止 HTTP Post 并关闭数据库的 Connection、Statement 和 ResultSet - 因为 Future.cancel() 不会为我执行此操作。当我在 Future 对象上调用 cancel() 时,我该怎么做?我是否必须存储包含 Future 对象、HttpPost、Connection、Statement 和 ResultSet 的数组列表?这似乎有点矫枉过正——肯定有更好的方法吗?

这是我现在拥有的一些代码,它只中止 HttpPost(而不是任何数据库对象)。

private static final ExecutorService pool = Executors.newFixedThreadPool(10);
public static Future<HttpClient> upload(final String url) {
    CallableTask ctask = new CallableTask();
    ctask.setFile(largeFile);
    ctask.setUrl(url);
    Future<HttpClient> f = pool.submit(ctask); //This will create an HttpPost that posts 'largefile' to the 'url'
    linklist.add(new tuple<Future<HttpClient>, HttpPost>(f, ctask.getPost())); //storing the objects for when I cancel later
    return f;
}


//This method cancels all running Future tasks and aborts any POSTs in progress
public static void cancelAll() {
    System.out.println("Checking status...");

    for (tuple<Future<HttpClient>, HttpPost> t : linklist) {
        Future<HttpClient> f = t.getFuture();
        HttpPost post = t.getPost();
        if (f.isDone()) {
            System.out.println("Task is done!");
        } else {
            if (f.isCancelled()) {
                System.out.println("Task was cancelled!");
            } else {
                while (!f.isDone()) {
                        f.cancel(true);
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("!Aborting Post!");
                        try {
                            post.abort();
                        } catch (Exception ex) {
                            System.out.println("Aborted Post, swallowing exception: ");
                            ex.printStackTrace();
                        }

                }
            }
        }
    }
}

有没有更简单的方法或更好的设计?现在我终止所有处理线程 - 将来,我想终止单个线程。

4

2 回答 2

1

我认为保留所有要关闭的资源的列表并不是最好的方法。在您当前的代码中,似乎 HTTP 请求是由 发起的,CallableTask但关闭是由其他人完成的。在我看来,关闭资源是打开它的人的责任。

我会让CallableTask发起 HTTP 请求,连接到数据库并完成它的工作,当它完成或中止时,它应该关闭它打开的所有内容。这样,您必须只跟踪Future代表您当前正在运行的任务的实例。

于 2013-08-27T21:11:13.990 回答
0

我认为你的方法是正确的。取消线程时,您需要自己处理回滚

cancel() 只是为已经执行的线程调用 interrupt()。看看这里

http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

正如它所说

中断是对线程的指示,它应该停止正在做的事情并做其他事情。由程序员决定线程如何响应中断,但线程终止是很常见的。

被中断的线程会抛出 InterruptedException

当一个线程正在等待、休眠或以其他方式暂停很长时间并且另一个线程使用 Thread 类中的 interrupt() 方法中断它时。

因此,您需要针对可能出现中断的执行线程中提到的场景进行显式编码。

于 2013-08-27T21:03:12.703 回答