マルチスレッドは、PushRendererおよびPortableRendererと組み合わせて欠落していたリンクでした(http://wiki.icesoft.org/display/ICE/Ajax+Push+-+APIsを参照)。
これで、バッキングBeanに3つのスレッドがあります。1つは長い操作を実行するためのもので、もう1つはステータスをポーリングするためのもので、もう1つは新しいスレッドを生成してクライアントブラウザにUIコントロールを返すための「メイン」スレッドです。
メインスレッドが実行スレッドとポーリングスレッドの両方を開始すると、メインスレッドは終了し、元のHTTPリクエストを完了します。私のPortableRendererは次のように宣言されてPortableRender portableRenderer;
おり、私のinit()メソッド(クラスコンストラクターによって呼び出されます)には次のものが含まれています。
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
スレッド部分についてはimplements Runnable
、クラスで使用し、単一のクラスで複数のスレッドを処理するために、次のStackOverflowの投稿に従いました:1つのクラスで複数のスレッドを処理する方法は?
ここにいくつかのソースコードがあります。使用した明示的なソースコードを公開することはできませんが、これは機密情報を公開しない要約版です。私はそれをテストしていません、そして私はそれをgeditで書いたので、構文エラーがあるかもしれません、しかしそれは少なくともあなたが正しい方向に始めるのを手に入れるはずです。
public void init()
{
// This method is called by the constructor.
// It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
}
public void someBeanMethod(ActionEvent evt)
{
// This is a backing bean method called by some UI event (e.g. clicking a button)
// Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render
copyExecuting = true;
// Create a status thread and start it
Thread statusThread = new Thread(new Runnable() {
public void run() {
try {
// message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
message = "Copying...";
// initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
portableRenderer.render("fullFormGroup");
do {
progress = getProgress();
portableRenderer.render("fullFormGroup"); // render the updated progress
Thread.sleep(5000); // sleep for a while until it's time to poll again
} while (copyExecuting);
progress = getProgress();
message = "Finished!";
portableRenderer.render("fullFormGroup"); // push a render one last time
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
});
statusThread.start();
// create a thread which initiates script and triggers the termination of statusThread
Thread copyThread = new Thread(new Runnable() {
public void run() {
File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
copyExecuting = false; // this will caue the statusThread's do..while loop to terminate
}
});
copyThread.start();
}