Java超时功能不适用于以下代码

时间:2018-11-12 22:29:57

标签: java

我尝试使用以下方法为Java中的SQL查询设置1秒的时间限制: How to timeout a thread

public class App {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new Task());

        try {
            System.out.println("Started..");
            System.out.println(future.get(1, TimeUnit.SECONDS));
            System.out.println("Finished!");
        } catch (TimeoutException e) {
            future.cancel(true);
            System.out.println("Terminated!");
        }

        executor.shutdownNow();
    }
}

class Task implements Callable<String> {
    @Override
    public String call() throws Exception {
        try {
            // some codes to do query via SQL Server JDBC, assuming it takes 10 seconds.
            ResultSet result = statement.executeQuery();
            // some codes to print the query result
        return "Done";
        }
        catch (Exception e) {
            System.out.println();
            e.printStackTrace();
        }
    }
}

但是,我发现尽管它在1秒后打印了“ Terminated”,但该程序仍在运行并在10秒后打印了查询结果。为何不起作用以及如何解决它?

3 个答案:

答案 0 :(得分:3)

shutdownNow实际上并没有停止线程,它只是发送一个信号(该中断可以使该线程执行)。在Java中停止线程很棘手,因为当您可以仅仅杀死线程(使用Thread.stop)时,您实际上不应该这样做,因为您不知道线程处于什么状态以及它处于什么状态会留下来的。

您可以在documentation中找到更多信息。

答案 1 :(得分:3)

将来调用cancel并不能保证作业将被取消。这取决于定期检查中断,然后在检测到中断时中止的方法。 Statement.execute()不会这样做。

在您的情况下,假设您正在执行SQL语句,则Statement类(setQueryTimeout)中有一个方法可以实现您的目标,而无需通过其他方法过度设计超时

答案 2 :(得分:-1)

您可以采用的另一种方法是使用thread.sleep()方法。当我希望我的程序只是短暂或短时间地暂停时,我经常使用它。在参数中,以千为单位输入与秒对应的值。例如:

public static void main(String[] args) throws InterruptedException // Required for thread.sleep()
{
    System.out.println("Hi there.");
    Thread.sleep(2000); // Wait two seconds before running the next line of code
    System.out.println("Goodbye.");
}

这是非常基本的,但不仅可以用于字符串。希望这会有所帮助。