创建一个线程以在Spring Webserver中以超时运行任务

时间:2016-04-13 14:42:47

标签: java spring multithreading spring-mvc

我试图创建一个运行一组任务的线程,如果它没有在特定时间内完成(例如100秒),则会抛出异常。目前,我试图通过将任务封装到runnable对象中并使用ExecutorServiceFuture类来执行超时执行来实现此目的。但是,当我启动Webservice时,我得到了这个例外:

java.util.concurrent.ExecutionException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.localhostInterpolatorHealthCheck': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:202)

我在网上看到它并不像定义你自己的线程那么简单,并且开始在Spring上启动一个线程,所以我想知道如何做到这一点?我错过了什么?

2 个答案:

答案 0 :(得分:3)

试试这个:

   /**
     * Executes a task with a specified timeout.
     */
    public final class TimeoutController {

        /**
         * Do not instantiate objects of this class. Methods are static.
         */
        private TimeoutController() {
        }

        /**
         * Executes <code>task</code>. Waits for <code>timeout</code>
         * milliseconds for the task to end and returns. If the task does not return
         * in time, the thread is interrupted and an Exception is thrown.
         * The caller should override the Thread.interrupt() method to something that
         * quickly makes the thread die or use Thread.isInterrupted().
         * @param task The thread to execute
         * @param timeout The timeout in milliseconds. 0 means to wait forever.
         * @throws TimeoutException if the timeout passes and the thread does not return.
         */
        public static void execute(Thread task, long timeout) throws TimeoutException {
            task.start();
            try {
                task.join(timeout);
            } catch (InterruptedException e) {
                /* if somebody interrupts us he knows what he is doing */
            }
            if (task.isAlive()) {
                task.interrupt();
                throw new TimeoutException();
            }
        }

        /**
         * Executes <code>task</code> in a new deamon Thread and waits for the timeout.
         * @param task The task to execute
         * @param timeout The timeout in milliseconds. 0 means to wait forever.
         * @throws TimeoutException if the timeout passes and the thread does not return.
         */
        public static void execute(Runnable task, long timeout) throws TimeoutException {
            Thread t = new Thread(task, "Timeout guard");
            t.setDaemon(true);
            execute(t, timeout);
        }

        /**
         * Signals that the task timed out.
         */
        public static class TimeoutException extends Exception {
            /** Create an instance */
            public TimeoutException() {
            }
        }
    }

答案 1 :(得分:1)

您可以使用多个@async方法,然后从主代码流中运行它们,获取期货列表。超时通过后,您可以获得结果或停止执行(取消/终止)。

这会带来好处,因为您将调用spring托管bean,因此所有依赖注入属性都可供您使用。但是你应该小心你提交的工作/线程数量。

为了使用@async注释,您需要使用xml配置中的特定行或bean上的AsyncEnabled注释来启用异步内容。