Joh*_*hew 5 java multithreading javafx-2
我正在编写一个 JavaFX 应用程序,该应用程序接收套接字上的数据点并实时可视化它们。问题是JavaFX渲染速度太慢。我有一个运行速度足够快的 Swing 实现,但我需要使用 JavaFX。
我正在工作的限制是:
到目前为止,我的方法是使用 Canvas JavaFX 节点作为可视化控件,并让接收线程安排对 Canvas 的更新以便稍后在 JavaFX 应用程序线程中运行,如下所示。
public void onEvent(Event event) {
....do processing...
Platform.runLater(new Runnable() {
@Override
public void run() {
graphics.setFill(...);
graphics.fillRect(...);
}});
}
Run Code Online (Sandbox Code Playgroud)
我想到了几种可能加快速度的方法:
sceneCanvas.getGraphicsContext2D().drawImage(processingCanvas.snapshot(SnapshotParameters(), null) 0, 0);。这样做的缺点是我认为它不是线程安全的,并且快照调用似乎相对昂贵。您能建议一些潜在的方法吗?
谢谢你!
我认为主要问题是您的代码将太多绘图任务推送到 FX 应用程序线程的队列中。通常,每秒 60 次绘图操作就足够了,这等于显示器的刷新率。如果您收到的“传入数据”事件多于此,您将比必要的更频繁地绘制,从而浪费 CPU。因此,您必须将数据处理与绘画分离。
一种解决方案是使用AnimationTimer. 它的handle方法将在每个动画帧中被调用,因此通常每秒 60 次。动画计时器在处理新数据时处理重绘。
// generic task that redraws the canvas when new data arrives
// (but not more often than 60 times per second).
public abstract class CanvasRedrawTask<T> extends AnimationTimer {
private final AtomicReference<T> data = new AtomicReference<T>(null);
private final Canvas canvas;
public CanvasRedrawTask(Canvas canvas) {
this.canvas = canvas;
}
public void requestRedraw(T dataToDraw) {
data.set(dataToDraw);
start(); // in case, not already started
}
public void handle(long now) {
// check if new data is available
T dataToDraw = data.getAndSet(null);
if (dataToDraw != null) {
redraw(canvas.getGraphicsContext2D(), dataToDraw);
}
}
protected abstract void redraw(GraphicsContext context, T data);
}
// somewhere else in your concrete canvas implementation
private final RedrawTask<MyData> task = new RedrawTask<MyData>(this) {
void redraw(GraphicsContext context, MyData data) {
// TODO: redraw canvas using context and data
}
}
// may be called by a different thread
public void onDataReceived(...) {
// process data / prepare for redraw task
// ...
// handover data to redraw task
task.requestRedraw(dataToDraw);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3684 次 |
| 最近记录: |