【问题标题】:Issue when executing asynchronous tasks using ExecutorService使用 ExecutorService 执行异步任务时的问题
【发布时间】:2012-01-31 08:59:56
【问题描述】:

我问了一个问题earlier 关于 ExecutorService 和 Apache Velocity 初始化。快速回顾一下——我有一个 Java EE 前端,它接受用户请求,然后对于这些请求中的每一个,使用 ExecutorService(SingleThreadedExecutor 设置为守护进程)来启动一个冗长的工作流程。这个工作流程包含在一个库中并且可以工作通过eclipse以独立模式运行时,正如预期的那样。当从网站(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 有关。 任何意见或建议都会有很大帮助。

谢谢

【问题讨论】:

  • 您的代码不是有效的 Java 代码。可以肯定的是,它远非线程安全。向我们展示真正的代码,因为我们可能对假代码所做的所有更正都没有用。请尊重 Java 命名约定:您的代码很难阅读。
  • 我很抱歉。我现在已经修复了代码。

标签: java velocity freemarker executorservice hung


【解决方案1】:

您的代码不是线程安全的,因为您在所有线程实例之间共享configtemplate(并不断重新设置它们)。使其线程安全的最简单方法是在方法中创建configtemplate 局部变量而不是静态成员。正如@JBNizet 在 cmets 中指出的那样,mailBuilderab 有类似的问题。您可能想先查看一些有关面向对象编程基础的教程,然后再回到这个问题(提示,通常您应该避免使用静态成员变量,常量除外)。

【讨论】:

  • +1。变量 a 和 b 以及 mailBuilder 中的 returnMailstring 方法也不应该是静态的。
  • 啊,但是由于 ExecutorService 是 SingleThreadedExecutor ,不会只有 1 个线程访问它们吗?我正在尝试您的建议。
  • 我们还没有看到您如何使用您的执行程序。您至少有两个线程:请求处理线程和工作线程。您的代码不仅是非线程安全的,而且设计得很糟糕。从解决设计问题开始,至少看看它是否解决了问题。
  • 上面的方法我都试过了,可以说问题依旧。我的执行人是根据nos在下面的帖子里的回复--stackoverflow.com/questions/4907502/…
  • @ping - 发布您的更新代码和线程转储,显示您的代码卡在哪里
猜你喜欢
  • 2019-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
相关资源
最近更新 更多