我有这个用于更新图表的JavaFX任务:
public class LiveRAMPerformance
{
private static final int MAX_DATA_POINTS = 50;
private Series series;
private int xSeriesData = 0;
private ConcurrentLinkedQueue<Number> dataQ = new ConcurrentLinkedQueue<Number>();
private ExecutorService executor;
private AddToQueue addToQueue;
//private Timeline timeline2;
private NumberAxis xAxis;
public AreaChart<Number, Number> init()
{
xAxis = new NumberAxis(0, MAX_DATA_POINTS, MAX_DATA_POINTS / 10);
xAxis.setForceZeroInRange(false);
xAxis.setAutoRanging(false);
xAxis.setTickLabelsVisible(false);
xAxis.setTickMarkVisible(false);
xAxis.setMinorTickVisible(false);
NumberAxis yAxis = new NumberAxis();
yAxis.setAutoRanging(true);
//-- Chart
final AreaChart<Number, Number> sc = new AreaChart<Number, Number>(xAxis, yAxis)
{
// Override to remove symbols on each data point
@Override
protected void dataItemAdded(Series<Number, Number> series, int itemIndex, Data<Number, Number> item)
{
}
};
sc.setAnimated(false);
sc.setId("liveAreaChart");
sc.setTitle("Animated Area Chart");
//-- Chart Series
series = new AreaChart.Series<Number, Number>();
series.setName("Area Chart Series");
sc.getData().add(series);
// look up first series fill
Node node = sc.lookup(".default-color0.chart-series-area-fill");
// set the first series fill to translucent pale green
node.setStyle("-fx-fill: linear-gradient(#f2f2f2, #d4d4d4);"
+ " -fx-background-insets: 0 0 -1 0, 0, 1, 2;"
+ " -fx-background-radius: 3px, 3px, 2px, 1px;");
Node nodew = sc.lookup(".chart-series-area-line");
// set the first series fill to translucent pale green
nodew.setStyle("-fx-stroke: #989898; -fx-stroke-width: 1px; ");
executor = Executors.newCachedThreadPool(new ThreadFactory()
{
@Override
public Thread newThread(Runnable r)
{
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
addToQueue = new AddToQueue();
executor.execute(addToQueue);
//-- Prepare Timeline
prepareTimeline();
return sc;
}
private class AddToQueue implements Runnable
{
@Override
public void run()
{
try
{
// add a item of random data to queue
dataQ.add(Math.random());
Thread.sleep(1150);
executor.execute(this);
}
catch (InterruptedException ex)
{
//Logger.getLogger(MainApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//-- Timeline gets called in the JavaFX Main thread
private void prepareTimeline()
{
// Every frame to take any data from queue and add to chart
new AnimationTimer()
{
@Override
public void handle(long now)
{
addDataToSeries();
}
}.start();
}
private void addDataToSeries()
{
for (int i = 0; i < 20; i++)
{ //-- add 20 numbers to the plot+
if (dataQ.isEmpty())
break;
series.getData().add(new AreaChart.Data(xSeriesData++, dataQ.remove()));
}
// remove points to keep us at no more than MAX_DATA_POINTS
if (series.getData().size() > MAX_DATA_POINTS)
{
series.getData().remove(0, series.getData().size() - MAX_DATA_POINTS);
}
// update
xAxis.setLowerBound(xSeriesData - MAX_DATA_POINTS);
xAxis.setUpperBound(xSeriesData - 1);
}
}
当我最小化图表或切换面板时,任务i仍在运行并消耗CPU资源。如何让Task只有在用户可见的情况下才能运行?当我不可见时,我想释放资源。
修改
这可能是解决方案:
sc.visibleProperty().addListener(new ChangeListener<Boolean>()
{
@Override
public void changed(final ObservableValue<? extends Boolean> observableValue, final Boolean aBoolean, final Boolean aBoolean2)
{
System.out.println("####");
//To change body of implemented methods use File | Settings | File Templates.
}
});
答案 0 :(得分:1)
如果数据随时可用(即检索或计算不需要很长时间),那么您根本不需要所有的线程机制。只需使用Timeline
和KeyFrame
EventHandler
即可更新图表。然后,当图表从显示中移除时,您可以在pause()
上调用Timeline
,并在显示图表时调用play()
。
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1150),
event -> {
series.getData().add(new AreaChart.Data(xSeriesData++, Math.random()));
if (series.getData().size() > MAX_DATA_POINTS) {
series.getData().remove(0);
}
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
现在您可以摆脱Runnable
,AnimationTimer
,ConcurrentLinkedQueue
和ExecutorService
。
因此,举例来说,如果您的图表位于名为Tab
的{{1}}中,而chartTab
名为TabPane
,则可以
tabPane