私は複数のワーカースレッドと、これらのスレッドで何が起きているかを報告しているJavaFX GUIを持っています。JavaFXの複雑な並行性:ObservableListsと複数のワーカースレッドのプロパティを使用
スレッド間で多くのデータが共有されており、視覚化する必要があります。だから私はObservableListとPropertyを使って、JavaFXでデータを簡単に表示できるようにしています。
私は小さなサンプルアプリケーションを作成して、アプリケーションで起こったことに似たものを表示しました。 これは2つのリストを持ち、ワーカースレッドはあるリストから別のリストにデータを移動します。ステータス文字列は最新の状態に保たれます。 完全なサンプルコードは、http://codetidy.com/6569/で発見することができます(このコードはクラッシュします、後で参照)。ここ
は、共有ObservableListの&プロパティは以下のとおりです。
private ObservableList<String> newItems;
private ObservableList<String> readyItems;
private StringProperty status;
は、ここで彼らはJavaFXの中で使用されている方法は次のとおりです。
listViewA.setItems(processor.getNewItems());
listViewB.setItems(processor.getReadyItems());
statusLabel.textProperty().bind(processor.getStatus());
ワーカースレッドはこれらのリストとプロパティを更新しますが、もちろん、これはJavaFXスレッドで行う必要があります。 私はJavaFXのスレッド上で更新する必要はありませんでした場合、これはコードのようになります。
Runnable newItemAdder = new Runnable() {
@Override
public void run() {
while(true) {
synchronized (newItems) {
String newItem = checkForNewItem(); //slow
if (newItem != null) {
newItems.add(newItem);
newItems.notify();
}
if (newItems.size() >= 5)
status.set("Overload");
else
status.set("OK");
}
synchronized (readyItems) {
if (readyItems.size() > 10)
readyItems.remove(0);
}
try { Thread.sleep(200); } catch (InterruptedException e) { return; }
}
}
};
new Thread(newItemAdder).start();
Runnable worker = new Runnable() {
@Override
public void run() {
while(true) {
List<String> toProcess = new ArrayList<String>();
synchronized (newItems) {
if (newItems.isEmpty())
try { newItems.wait(); } catch (InterruptedException e) { return; }
toProcess.addAll(newItems);
}
for (String item : toProcess) {
String processedItem = processItem(item); //slow
synchronized (readyItems) {
readyItems.add(processedItem);
}
}
}
}
};
new Thread(worker).start();
コースオフ、いくつかのものがPlatform.runLaterで解決するのは簡単です:
Platform.runLater(new Runnable() {
@Override
public void run() {
synchronized (newItems) {
if (newItems.size() >= 5)
status.set("Overload");
else
status.set("OK");
}
}
});
の罰金だこと私がタスクに書き込むプロパティ/リストは、JavaFX GUIでのみ読み込みます。 しかし、この例では、同期、読み取り、書き込みが必要なリストの場合は非常に複雑になります。 Platform.runLaterをたくさん追加する必要があり、 "runLater"タスクが終了するまでブロックする必要があります。この結果、コードは非常に複雑で読みにくくなります(私はこのような方法でこの例を実行することができました。私が意味するところはhttp://codetidy.com/6570/です)。
私のサンプルを動作させる他の方法はありますか?私は
コードを変更しましたか?あなたはそれらを見せることができますか?JewelSeaの最後のリンクは機能しません – AloneInTheDark
@AloneInTheDark私は見回しましたが、元のサンプルコードもjewelseaの修正版もありません。私は解決策の要約とともに余分な回答を掲示しました。 –