Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Glassfish 4-使用并发API创建托管线程_Java_Multithreading_Glassfish_Java Ee 7 - Fatal编程技术网

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

Java Glassfish 4-使用并发API创建托管线程,java,multithreading,glassfish,java-ee-7,Java,Multithreading,Glassfish,Java Ee 7,我正在尝试使用新的并发API来注入一个并使用它 下面是我所说的一个例子: @Singleton @Startup public class Demo { @Resource(name="concurrent/__DefaultManagedThreadFactory") ManagedThreadFactory threadFactory; @PostConstruct public void startup() { threadFactory.newT

我正在尝试使用新的并发API来注入一个并使用它

下面是我所说的一个例子:

@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();
    }
}
我正在Eclipse中使用Glassfish插件进行开发。在进行更改后重新发布时,我总是在服务器日志中看到这一行。每次调用start()时,它都会出现一次:

它实际上并没有抛出一个非法状态异常,只是报告一个被抛出(并捕获)到玻璃鱼里面。应用程序正常部署,但没有线程启动。如果我随后重新发布并再次发布,那么“错误”将消失,线程将按预期启动

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

我是否正确使用了并发API?可能是配置问题吗?作为记录,如果改用ManagedExcecutorService,我会得到相同的行为


为了记录在案,几个月前在这里有人问过这个问题:,但它并没有得到真正的回答,而且我还没有名声去做任何事情,只是再问一次。对不起


更新:由works提供。非常感谢。我对该解决方案进行了一些重构,试图将解决方案代码与原始应用程序逻辑隔离开来:

@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();            
    }

}

/**
*一个实用类,用于绕过Glassfish中的一个bug,该bug允许
*并发资源(ManagedThreadFactory、ManagedExecutorService等)
*在准备使用前进行注射。
* 
*从Per Axel Felth的溶液中提取:https://stackoverflow.com/questions/23900826/glassfish-4-using-concurrency-api-to-create-managed-threads
*/
@独生子女
公共类并发初始化器{
/**
*尝试执行之前要等待的毫秒数
*/
公共静态最终长重试延迟=500L;
/**
*失败前进行的最大并发尝试次数
*/
公共静态最终整数最大重试次数=20次;
/**
*反复尝试向注入的ManagedExecutorService提交可运行任务
*触发并发资源的准备。
* 
*@return true如果成功(并发资源现在可以使用),
*如果超时,则为false
*/
公共布尔init(){
最终原子布尔完成=新原子布尔(false);
int i=0;
试一试{
而(!done.get()&&i++
我怀疑您的ManagedThreadFactory没有正确注入,因此“演示”组件没有启动

JavaEE7规范要求在JNDI中提供名为“Java:comp/DefaultManagedThreadFactory”的托管线程工厂,因此请尝试将@Resource更改为

@Resource(name="java:comp/DefaultManagedThreadFactory")
我不熟悉Glassfish(我是一个野蝇类的家伙),但你可能在任何JNDI树显示中都看不到这个参考。它可能在内部链接到“concurrent/_DefaultManagedThreadFactory”(顺便说一句,它不是资源名称)

如果失败,你也可以尝试

@Resource(lookup="concurrent/__DefaultManagedThreadFactory")

它与一种玻璃鱼虫有关。不久前,我自己也遇到了同样的错误,并建立了一个解决方案。问题是,线程工厂是注入好的,但如果你使用它“太早”,你将以一个非法状态异常结束

下面列出了我的解决方案代码。它使用注入的executor服务来检测何时加载应用程序以及并发UTIL是否可用,然后执行方法
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();
    }
}
@Singleton
@启动
公开课演示{
@资源(name=“concurrent/\uuu DefaultManagedThreadFactory”)
ManagedThreadFactory线程工厂;
@资源
ManagedExecutorService执行器服务;
@EJB
演示我;
@施工后
公共无效启动(){
me.waitAndInitialize();
}
@异步的
公共未来等待和初始化(){
试一试{
最终AtomicInteger完成=新的AtomicInteger(0);
int i=0;
while(done.intValue()==0&&i<20){
System.out.println(“执行器服务启动了吗?”);
i++;
执行器服务。提交(
新的Runnable(){
@凌驾
公开募捐{
int incrementAndGet=done.incrementAndGet();
System.out.println(“由executorservice运行”);
}
});
睡眠(500);
}
if(done.intValue()==0){
Logger.getAnonymousLogger().severy(“等待ExecutorService准备好很长时间,但它从未准备好。将不会初始化!”);
}否则{
init();
}
}捕获(例外e){
Logger.getAnonymousLogger().log(Level.severy,“waitAndInitialize中的异常:”+e.getMessage(),e);
}
返回新的异步结果(空);
}
私有void init(){
threadFactory.newThread(
新的Runnable(){
@凌驾
公开募捐{
System.out.println(“做点什么”);
}
}
).start();
}
}

谢谢您的回复。我更改了注入的@Resource的名称,但仍然得到相同的行为。但我认为你是对的,看起来ManagedThreadFactory
@Resource(lookup="concurrent/__DefaultManagedThreadFactory")
@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();
    }
}