5

@ Singleton、@ Schedule、@ Timeoutアノテーションを使用して簡単な例を作成し、問題が解決するかどうか試してみました。

シナリオは次のとおりです。EJBは5秒ごとに「check」関数を呼び出し、特定の条件が満たされると、非同期的に長時間実行されるプロセスを呼び出すシングルアクションタイマーを作成します。(これは一種のキュー実装タイプのものです)。その後、チェックを続行しますが、長時間実行されているプロセスが存在している間は、別のプロセスを開始しません。

以下は私が思いついたコードですが、私が行っている非同期呼び出しが実際に@Scheduleメソッドをブロックしているように見えるため、このソリューションは機能しません。

@Singleton
@Startup
public class GenerationQueue {

    private Logger logger = Logger.getLogger(GenerationQueue.class.getName());

    private List<String> queue = new ArrayList<String>();

    private boolean available = true;

    @Resource
    TimerService timerService;

    @Schedule(persistent=true, minute="*", second="*/5", hour="*")
    public void checkQueueState() {

        logger.log(Level.INFO,"Queue state check: "+available+" size: "+queue.size()+", "+new Date());

        if (available) {

            timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
        }

    }

    @Timeout
    private void generateReport(Timer timer) {

        logger.info("!!--timeout invoked here "+new Date());

        available = false;

        try {

            Thread.sleep(1000*60*2); // something that lasts for a bit

        } catch (Exception e) {}

        available = true;

        logger.info("New report generation complete");

    }

ここで何が欠けているのですか、それとも別のアプローチを試す必要がありますか?どんなアイデアでも大歓迎です:)

Glassfish3.0.1最新ビルドでのテスト-言及するのを忘れた

4

1 に答える 1

11

シングルトンのデフォルトの @ConcurrencyManagement は ConcurrencyManagementType.CONTAINER で、デフォルトの @Lock は LockType.WRITE です。基本的に、これはすべてのメソッド (generateReports を含む) が synchronized キーワードで効果的にマークされていることを意味します。これは、generateReport の実行中に checkQueueState がブロックされることを意味します。

ConcurrencyManagement(ConcurrencyManagementType.BEAN) または @Lock(LockType.READ) の使用を検討してください。どちらの提案も役に立たない場合は、Glassfish のバグを見つけたのではないかと思います。

余談ですが、サーバーがオフラインの場合でも checkQueueState メソッドが 5 秒ごとに起動することを保証する必要はおそらくないため、persistent=false が必要になるでしょう。つまり、サーバーをオンラインに戻すときにコンテナーが「キャッチアップ」を開始する必要はおそらくないでしょう。

于 2010-04-23T05:21:46.313 に答える