0

在这个最简单的例子中我做错了什么?(Glassfish 4.0-b87 + Eclipse 开普勒 m6)

我自己.java

package com.example.cancelbug;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;

@Singleton
@Startup
public class Myself {
  @Inject Other other;
  private Future < Integer > future;

  @PostConstruct
  public void post_construct () {
    System.out.println("post_construct started");
    future = other.ton_of_work();
    System.out.println("post_construct ended");
  }

  @PreDestroy
  public void pre_destroy () {
    System.out.println("pre_destroy started");
    System.out.println("cancel result: " + Boolean.toString(future.cancel(true)));
    try {
      System.out.println("future result: " + future.get().toString());
    } catch (InterruptedException | ExecutionException e) {
      System.out.println("future result: interrupted");
      Thread.currentThread().interrupt();
      System.out.println("thread reinterrupted");
    }
    System.out.println("pre_destroy ended");
  }
}

其他.java

package com.example.cancelbug;

import java.util.concurrent.Future;

import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

@Stateless
public class Other {
  @Asynchronous
  public Future < Integer > ton_of_work () {
    System.out.println("other: ton_of_work started");
    int i;
    for (i = 0; i < 10; ++i) {
      try {
        System.out.println("other: take a nap");
        Thread.sleep(1000L);
        System.out.println("other: woke up: " + Integer.toString(i));
      } catch (InterruptedException e) {
        System.out.println("other: ton_of_work interrupted");
        Thread.currentThread().interrupt();
        break;
      }
    }
    System.out.println("other: ton_of_work returning");
    return new AsyncResult < Integer >(new Integer(i));
  }
}

输出

post_construct started
post_construct ended
other: ton_of_work started
other: take a nap
other: woke up: 0
other: take a nap
other: woke up: 1
other: take a nap
other: woke up: 2
other: take a nap
pre_destroy started
cancel result: false            <<<<<<< expected true; ton_of_work: interrupted
other: woke up: 3               <<<<<<< expected no such output
other: take a nap               <<<<<<< expected no such output
other: woke up: 4               <<<<<<< expected no such output
other: take a nap               <<<<<<< expected no such output
other: woke up: 5               <<<<<<< expected no such output
other: take a nap               <<<<<<< expected no such output
other: woke up: 6               <<<<<<< expected no such output
other: take a nap               <<<<<<< expected no such output
other: woke up: 7               <<<<<<< expected no such output
other: take a nap               <<<<<<< expected no such output
other: woke up: 8               <<<<<<< expected no such output
other: take a nap               <<<<<<< expected no such output
other: woke up: 9               <<<<<<< expected no such output
other: ton_of_work returning
future result: 10               <<<<<<< expected 2
pre_destroy ended

预期输出:

post_construct started
post_construct ended
other: ton_of_work started
other: take a nap
other: woke up: 0
other: take a nap
other: woke up: 1
other: take a nap
other: woke up: 2
other: take a nap
pre_destroy started
cancel result: true             <<<<<<< actual false
other: ton_of_work interrupted  <<<<<<< actual missing
other: ton_of_work returning
future result: 2                <<<<<<< actual 10
pre_destroy ended
4

1 回答 1

9

EJB 3.1 只提供协作异步中断;也就是说,EJB 可以检查客户端是否调用了取消。即使调用 Future.cancel(true) 也无法获得实际的 Thread.interrupt。

有一个开放的 EJB 规范问题 ( EJB_SPEC-73 ) 允许实际的线程中断。这在EJB 3.2专家组(1、2、3、4、5、6 上进行了讨论但讨论最终推迟到了 EJB 规范的下一版本

于 2013-05-11T14:46:13.447 回答