该
message属性被设计为包含的“当前消息”的属性,
task即目标用例类似于状态消息。在此用例中,仅在非常短的时间内存储在属性中的消息不会被截取并不重要。实际上,有关
updateMessage()状态的文档:
对updateMessage的调用被合并,并稍后在FX应用程序线程上运行,因此,即使从FX
Application线程对updateMessage的调用也不一定会导致对该属性的立即更新,并且 中间消息值可能会被合并以保存事件通知 。
(我的重点)。因此,简而言之,如果传递给它们的某些值很快被另一个值所取代
updateMessage(...),
messageProperty则可能实际上不会设置为这些值。通常,每次将一帧渲染到屏幕上时,您都只能观察到一个值(每秒60次或更少)。如果您有一个重要的用例,那就要观察每个值,那么您就需要使用另一种机制。
一个非常幼稚的实现将只使用
Platform.runLater(...)并直接更新文本区域。我不推荐这种实现方式,因为您冒着太多调用淹没FX
Application Thread的风险(
updateMessage(...)合并调用的确切原因),使UI 无法响应。但是,此实现如下所示:
for (int i = 1 ; i <= 300; i++) { String value = "n" + i ; Platform.runLater(() -> ta_Statusbereich.appendText(value));}另一种选择是使每个操作成为一个单独的任务,并在某个执行程序中并行执行它们。附加到每个任务
onSucceeded处理程序中的文本区域。在此实现中,结果的顺序不是预先确定的,因此,如果顺序很重要,则这不是适当的机制:
final int numThreads = 8 ;Executor exec = Executors.newFixedThreadPool(numThreads, runnable -> { Thread t = Executors.defaultThreadFactory().newThread(runnable); t.setDaemon(true); return t ;});// ...for (int i = 1; i <= 300; i++) { int value = i ; Task<String> task = new Task<String>() { @Override public String call() { // in real life, do real work here... return "n" + value ; // value to be processed in onSucceeded } }; task.setonSucceeded(e -> ta_Statusbereich.appendText(task.getValue())); exec.execute(task);}如果要通过单个任务完成所有这些操作并控制顺序,则可以将所有消息放入中
BlockingQueue,从阻止队列中提取消息,并将其放置在FX
Application线程的文本区域中。为确保您不会在FX
Application线程中进行过多的调用,每帧渲染到屏幕上的消息应最多消耗一次队列中的消息。您可以
AnimationTimer为此使用一个:
handle保证每个帧渲染都调用一次它的方法。看起来像:
BlockingQueue<String> messageQueue = new linkedBlockingQueue<>();Task<Void> task = new Task<Void>() { @Override public Void call() throws Exception { final int numMessages = 300 ; Platform.runLater(() -> new MessageConsumer(messageQueue, ta_Statusbereich, numMessages).start()); for (int i = 1; i <= numMessages; i++) { // do real work... messageQueue.put(Integer.toString(i)); } return null ; }};new Thread(task).start(); // or submit to an executor...// ...public class MessageConsumer extends AnimationTimer { private final BlockingQueue<String> messageQueue ; private final textarea textarea ; private final numMessages ; private int messagesReceived = 0 ; public MessageConsumer(BlockingQueue<String> messageQueue, textarea textarea, int numMessages) { this.messageQueue = messageQueue ; this.textarea = textarea ; this.numMessages = numMessages ; } @Override public void handle(long now) { List<String> messages = new ArrayList<>(); messagesReceived += messageQueue.drainTo(messages); messages.forEach(msg -> textarea.appendText("n"+msg)); if (messagesReceived >= numMessages) { stop(); } }}


