当前位置: 首页 > 面试题库 >

使用ExecutorService执行异步任务时出现问题

穆展鹏
2023-03-14
问题内容

快速回顾一下-我有一个Java
EE前端,可以接受用户请求,然后针对每个请求使用ExecutorService(SingleThreadedExecutor设置为守护程序)启动冗长的工作流,该工作流包含在库中并且可以工作很好,并且在通过Eclipse以独立模式运行时按预期运行。当从website(servlet)调用时,我观察到工作流始终在初始化Velocity
Engine(Velocity.init()或ve.init())时挂起。因此,我前面提到的问题。

当所有答案/建议都无效时,我推断这与Velocity的启动方式有关,并决定改用FreeMarker。现在,我看到FreeMarker实现的工作流程也被挂在了完全相同的位置。这个``地方’‘是邮件构建的一部分,它根据大量传递的数据对象评估模板并返回邮件字符串。调用Freemark’ing类和FreeMark类的类如下-

   public class mailBuilder {

    private static final Logger log = Logger.getLogger( mailBuilder.class );    
    static String a;
    static String b;

    public mailBuilder(CustomDataStructure input)
    {
        a = input.getA();
        b = input.getB(); 
    }
    public static String returnMailstring() throws Exception
    {
        log.info("Gathering elements to construct email.");
        String mailText=null;
        Map context = new HashMap();
        context.put("a",a);
        context.put("b",b);
        log.info("Calling Freemarker");
        mailText=FreeMarkIT.ReturnReportString(context);
        log.info("Freeemarker returned string");

        return mailText;
    }
}

FreeMarkIT类如下-

    public class FreeMarkIT {
        private static final Logger log = Logger.getLogger( FreeMarkIT.class );
        private static Configuration config;
        private static Template template;

        public static String ReturnReportString(Map model) throws IOException, TemplateException
        {
            StringWriter sw = new StringWriter();
            try 
            {
               log.info("Going to get the template");
               config= new Configuration();
               log.info("Now really");
               template=config.getTemplate("src/resource/email_template.vm");
               log.info("Done initializing template");
               template.process(model, sw);
               sw.flush();
            }
            catch(Exception e)
            {
                System.out.println(e.getMessage());
            }

            return sw.getBuffer().toString();
        }
    }

现在,从我的日志记录看来,工作线程挂在了该行 config=new Configuration()

同样,从Eclipse运行时,它可以在独立模式下按预期方式工作,但是当使用ExecutorService从servlet调用时,则挂起。

我开始思考/意识到这可能与Velocity或FreeMarker无关,而与ExecutorService无关。任何建议或建议都会有很大帮助。

谢谢


问题答案:

你的代码是不是线程安全的,因为你是共享configtemplate跨所有线程实例(不断重新设置它们)。使它成为线程安全的最简单方法是在方法中使用configtemplate局部变量,而不是静态成员。作为@JBNizet在评论中指出,你有类似的问题mailBuilderab。您可能想先阅读一些有关面向对象编程基础的教程,然后再回过头看这个问题(提示,通常应避免使用除常量以外的静态成员变量)。



 类似资料:
  • 这是在一次Android采访中被问到的。有人问我是否可以从异步任务 1 的 doInBackground() 方法(让它成为 Task1)启动另一个异步任务(让它成为 Task2)。我浏览了文档,其中说了以下内容: 必须在UI线程上创建任务实例。 必须在 UI 线程上调用 execute(Params...)。 根据这些陈述,我认为从另一个任务的后台方法启动一个任务是不可能的。此外,async任务

  • 在Server程序中如果需要执行很耗时的操作,比如一个聊天服务器发送广播,Web服务器中发送邮件。如果直接去执行这些函数就会阻塞当前进程,导致服务器响应变慢。 Swoole提供了异步任务处理的功能,可以投递一个异步任务到TaskWorker进程池中执行,不影响当前请求的处理速度。 程序代码 基于第一个TCP服务器,只需要增加onTask和onFinish 2个事件回调函数即可。另外需要设置task

  • 我有一个数十万对象的列表。当每一个运行时,它都会根据给定的值执行一个可能很长的计算。正因为如此,我希望异步运行每个任务(最好是通过使用某种执行器),并在30秒后检索每次计算的结果,取消那些没有及时完成的结果。(所得值在其他地方使用。) 到目前为止,我就是这样实现它的: ArrayList存储每个要执行的,然后将其发送到ExecutorService以运行所有任务。我遇到的问题是,任务似乎是同步启动

  • 我已经使用ExecutorService实现了超时任务。在下面的方法中,我正在提交超时任务,如果它在给定的时间内超时,我将取消该任务并关闭执行器。 它运行得很好,我没有任何问题。 然而,我想知道这是否是最好的代码设计。我只是想知道如果使用ExecutorService返回的未来是否会更好。submit()获取可调用函数的返回值或超时超时任务。例如 我正在使用JDK7。

  • 我使用java.util.concurrent.ExecutorService和固定线程池来执行任务列表。我的任务列表通常在80-150个左右,我已经将任何时候运行的线程数限制为10个,如下所示: 我的用例要求即使完成的任务也应该重新提交给ExecutorService,但是只有当所有已经提交的任务都被服务/完成时,才应该再次执行/获取。也就是说,提交的任务基本上应该轮流执行。因此,在这种情况下不

  • 问题内容: 我们有一个问题。:) 我们要确保任何时候只有N个线程在执行后台任务。为此,我们使用了固定线程池执行程序。它似乎工作正常。 然后我们发现了一个问题。假设您有一个使用执行程序执行一些并行工作的类,然后在执行程序线程中调用了另一个类,该线程也执行一些并行工作,打算等待它。这是发生了什么: 主线程调用第一级方法。 这种方法认为它可以并行化为16个任务,并拆分其工作。 16个任务被提交给执行者。