Glassfish 4 - 使用并发 API 创建托管线程

2024-01-26

我正在尝试使用新的 Concurrency API 来注入托管线程工厂 http://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedThreadFactory.html并使用它Oracle 教程 http://docs.oracle.com/javaee/7/tutorial/doc/concurrency-utilities006.htm.

这是我正在谈论的一个例子:

@Singleton
@Startup
public class Demo {
    @Resource(name="concurrent/__DefaultManagedThreadFactory") ManagedThreadFactory threadFactory;

    @PostConstruct
    public void startup() {
        threadFactory.newThread(
            new Runnable() {
                @Override
                public void run() {
                    System.out.println("Do something.");
                }
            }
        ).start();
    }
}

我正在使用 Glassfish 插件在 Eclipse 中进行开发。当我进行更改后重新发布时,我总是在服务器日志中看到这一行。我们每次调用 start() 时它都会出现一次:

SEVERE: java.lang.IllegalStateException: Module (my application) is disabled

它实际上并没有抛出 IllegalStateException,只是报告已在 Glassfish 中抛出(并捕获)一个 IllegalStateException。应用程序正常部署,但没有线程启动。如果我随后重新发布并第二次,“错误”就会消失并且线程会按预期启动。

当我尝试将应用程序部署到“真正的”Glassfish 设置(没有 Eclipse)时,它总是报告部署成功,并且日志不包含“错误”。但它仍然不会启动线程(即使重复部署)。

我是否正确使用了并发 API?会不会是配置问题?根据记录,如果我使用 ManagedExcecutorService ,我会得到相同的行为。


根据记录,这个问题是几个月前在这里提出的:我可以在 Singleton Enterprise Java Bean 中启动 ManagedThread 吗? https://stackoverflow.com/questions/20446682/can-i-start-a-managedthread-in-a-singleton-enterprise-java-bean,但它并没有得到真正的答复,而且我除了再次询问之外还没有做任何事情的声誉。对不起!


UPDATE: 这个答案 https://stackoverflow.com/a/28360042/3593206 by 佩阿克塞尔·费尔斯 https://stackoverflow.com/users/1806345/per-axel-felth作品。谢谢你!我对该解决方案进行了一些重构,以尝试将解决方法代码与我的原始应用程序逻辑隔离:

@Singleton
@Startup
public class Demo {

    @Resource(name="java:comp/DefaultManagedThreadFactory") ManagedThreadFactory threadFactory;
    @EJB private ConcurrencyInitializer concurrencyInitializer;
    @EJB private Demo self;

    @PostConstruct
    public void startup() {
        self.startThread();
    }

    @Asynchronous
    public void startThread() {
        //This line applies the workaround
        concurrencyInitializer.init();

        //Everything beyond this point is my original application logic
        threadFactory.newThread(
            new Runnable() {
                @Override
                public void run() {
                    System.out.println("Do something.");
                }
            }
        ).start();            
    }

}

 

/**
 * A utility class used to get around a bug in Glassfish that allows
 * Concurrency resources (ManagedThreadFactory, ManagedExecutorService, etc)
 * to be injected before they are ready to be used. 
 * 
 * Derived from solution by Per-Axel Felth in: https://stackoverflow.com/questions/23900826/glassfish-4-using-concurrency-api-to-create-managed-threads
 */
@Singleton
public class ConcurrencyInitializer {
    /**
     * The number of milliseconds to wait before try to 
     */
    public static final long RETRY_DELAY = 500L;

    /**
     * The maximum number of concurrency attempts to make before failing
     */
    public static final int MAX_RETRIES = 20;

    /**
     * Repeatedly attempts to submit a Runnable task to an injected ManagedExecutorService
     * to trigger the readying of the Concurrency resources.
     * 
     * @return true if successful (Concurrency resources are now ready for use),
     *         false if timed out instead
     */
    public boolean init() {
        final AtomicBoolean done = new AtomicBoolean(false);
        int i = 0;

        try {
            while (!done.get() && i++ < MAX_RETRIES) {
                executorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        done.set(true);
                    }
                });
                Thread.sleep(RETRY_DELAY);
            }
        } catch(InterruptedException e) {
            //Do nothing.
        } 

        return done.get();
    }
}

它与 Glassfish 错误有关。我自己不久前也遇到了同样的错误并构建了一个解决方法。事实是,线程工厂被注入了,但是如果你“太早”使用它,你最终会得到一个 IllegalStateException。

下面列出了我的解决方法代码。它使用注入的执行程序服务来检测应用程序何时加载以及并发实用程序是否可用,然后在方法中执行实际的启动逻辑init.

@Singleton
@Startup
public class Demo {

    @Resource(name = "concurrent/__DefaultManagedThreadFactory")
    ManagedThreadFactory threadFactory;
    @Resource
    ManagedExecutorService executorService;
    @EJB
    Demo me;

    @PostConstruct
    public void startup() {

        me.waitAndInitialize();
    }

    @Asynchronous
    public Future<?> waitAndInitialize() {
        try {
            final AtomicInteger done = new AtomicInteger(0);
            int i = 0;

            while (done.intValue() == 0 && i < 20) {
                System.out.println("Is executor service up?");

                i++;

                executorService.submit(
                        new Runnable() {

                            @Override
                            public void run() {
                                int incrementAndGet = done.incrementAndGet();
                                System.out.println("Run by executorservice");
                            }
                        });
                Thread.sleep(500);
            }

            if (done.intValue() == 0) {
                Logger.getAnonymousLogger().severe("Waited a long time for the ExecutorService do become ready, but it never did. Will not initialize!");
            } else {
                init();
            }
        } catch (Exception e) {
            Logger.getAnonymousLogger().log(Level.SEVERE, "Exception in waitAndInitialize: " + e.getMessage(), e);
        }

        return new AsyncResult<>(null);
    }

    private void init() {
        threadFactory.newThread(
                new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("Do something.");
                    }
                }
        ).start();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Glassfish 4 - 使用并发 API 创建托管线程 的相关文章

  • 如何根据 JComboBox 选择动态地将控件添加到表单?

    我正在尝试使用 Swing 创建一个简单的 java 表单 这个想法的基本思想是用户将在 JComboBox 中选择 0 到 5 然后 通过 ItemStateChanged 侦听器 将动态添加几个面板 每个面板包含 4 个控件 因此 如果
  • 在游戏框架中编写功能测试的正确方法

    在为基于 play1 2 4 的 web 应用程序编写功能测试时 我对如何正确编码感到有点困惑 困惑在于所涉及的事务边界 我在某处读到每个测试都有自己的事务 在我的应用程序中 用户可以登录并向购物车添加一些商品 然后他可以提供一个地址 以便
  • 从 Java 启动外部进程:stdout 和 stderr

    我正在使用标准从 java 启动一个外部进程java lang Process 我试图弄清楚该过程的输出是什么 但是采用结合了两者的格式stdout and stderr 目前 我有Process getInputStream它提供了访问s
  • AES BadPaddingException

    如果我使用错误的密钥或错误的盐进行解密 则会引发 BadPaddingException 我希望返回一个不正确的字符串 doFinal 导致解密方法出现异常 信息 This is just an example Unfug S F V s
  • Eclipse 内容协助无法在枚举常量参数列表中工作

    使用 eclipse 当我输入以下内容时 public enum Foo A Integer private final Integer integer private Foo Integer integer this integer in
  • Java 中的 TreeSet 与 C#.net 的等效项

    我有 Java 代码 其中包含TreeSet 我想将代码转换为 C 我可以使用哪个等效集合 如果没有 请提出替代方案 那将是系统 集合 通用 SortedSet
  • Hibernate、MySQL 视图和 hibernate.hbm2ddl.auto = 验证

    我可以在 Hibernate 中使用 MySQL 视图 将它们视为表 即 该实体与为表创建的实体没有什么不同 但是 当 Hibernate 设置为验证模型时 我的应用程序将不会部署 因为它找不到视图 因为它假设它是一个表 是否可以在启用部署
  • 当用户使用相同的凭据登录两次时如何使用户会话无效

    我正在使用带有 Richfaces 和 Facelets 的 JSF 1 2 我有一个应用程序 其中包含许多会话范围的 Bean 和一些应用程序 Bean 假设用户使用 Firefox 登录 创建一个会话 ID A 然后他打开 Chrome
  • APACHE POI 从 Java 中的 Excel 获取精确的字体颜色

    在 Excel 工作表中 如何使用 Java 中的 Apache POI 获取准确的字体颜色值 我试图通过使用来获取字体颜色 org apache poi ss usermodel Font f book getFontAt style g
  • 使用 Lint 和 SonarQube 分析 Android 项目

    我真的 溢出 了试图让这些东西一起工作 我按照这里的指示进行操作 http docs sonarqube org display PLUG Android Lint Plugin http docs sonarqube org displa
  • org.apache.catalina.core.JreMemoryLeakPreventionListener 中急切调用 URLConnection 的 setDefaultUseCaches(false) 是什么原因

    这个问题可能有点难以找到答案 这是一个系列中的问题考虑使用 Policy getPolicy 的原因是什么 因为它将保留对上下文的静态引用并可能导致内存泄漏 https stackoverflow com questions 7057421
  • 从字符串中提取文本 Java

    使用此字符串 ADACADABRA 如何从java中的字符串 ADACADABRA 中提取 CADA 以及如何提取 和 之间的id从下面的链接 http www youtube nocookie com embed zaaU9lJ34c5
  • System.out.println("嗨"+6+10);打印Hi610?

    为什么要这样做 太令人困惑了 运算符优先级和结合性 两点 操作员 如果一个或两个参数都是字符串 则进行字符串连接 操作员 从左到右工作 所以在你的例子中 Hi 6 is Hi6 and Hi6 10 is Hi610 编辑 正如您在对另一个
  • 为什么我的 Java 路径中添加了“L”?

    我在我的类路径中加载了一个 jar 在 iReport 中 如果重要的话 我确信它具有所需的方法 但是当我尝试测试连接 从而调用该 jar 时 我得到一个 java lang NoSuchMethodError 说它正在引用班上 Lorg
  • JSF - 实施受限页面过滤器

    我正在关注 BalusC 的回答JSF 2 0 如何获取在浏览器地址栏中输入的 URL https stackoverflow com questions 4105263 jsf 2 0 how to get the url that is
  • 同时运行 x 个网络请求

    我们公司有一个网络服务 我想通过我自己的服务发送 XML 文件 存储在我的驱动器上 HTTPWebRequestC 中的客户端 这已经有效了 Web服务同时支持5个同步请求 一旦服务器上的处理完成 我就会从Web服务获得响应 每个请求的处理
  • 需要同步仅增量计数器吗?

    我使用整数作为计数器 该整数只会增加 并且肯定有多个线程会同时增加它 当没有其他线程尝试访问其值时 在程序执行结束时读取该计数器的值 我假设我不必为这种仅增量计数器使用锁或任何类型的同步 这是正确的吗 如果这有什么区别的话 我用 Java
  • JavaFX 中的 MVC 模式与场景生成器

    我是 JavaFX 新手 根据我当前的设置 正在努力创建合适的 MVC 架构 我使用 Scene Builder 单击了一个 UI 并指定了一个 Controller 类 Startup public class Portal extend
  • 如何使用 Kafka 发送大消息(超过 15MB)?

    我发送字符串消息到Kafka V 0 8使用 Java Producer API 如果消息大小约为 15 MB 我会得到MessageSizeTooLargeException 我尝试过设置message max bytes到 40 MB
  • Java分数计算器

    我对 Java 编程还很陌生 我的 AP 计算机编程课程有作业要完成 所以请耐心等待 我必须弄清楚如何将两个分数相乘 我想知道是否有任何方法可以在方法内部声明变量并在该方法外部使用它 我在介绍方法中的 while 循环 谢谢您 希望这不会令

随机推荐