项目当中有一个需求,目的是通过串口服务器读取12个岗位上的PLC数据,并实时(每隔500ms)显示在界面当中。
在需求中提到了每隔500ms,所以需要创建一个每隔500ms执行的定时任务。
同时获取12个岗位中的PLC数据,则需要创建12个线程用来同步获取数据。
首先创建定时任务:
//在主线程中开启定时任务,由于是在JavaFx的main中,故省略了JavaFx部分。
private static ScheduledService testScheduledService = null;
/**
* 不与JavaFX Application结合会报:Exception in thread "main" java.lang.IllegalStateException: Toolkit not initialized
*/
private static void executeScheduledService(){
//设置间隔500ms
Integer time = 500;
if(StringUtil.isNotEmpty(timeStr)) {
time =Integer.parseInt (timeStr);
}
testScheduledService = new ScheduleService();
// 设置线程池,restart会尝试重用线程
testScheduledService.setExecutor(Executors.newFixedThreadPool(12));
// 延时1s开始
testScheduledService.setDelay(Duration.millis(1000));
// 间隔1s执行
testScheduledService.setPeriod(Duration.millis(time));
testScheduledService.start();
// delay和period的设置时间经过之后,ScheduledService Delay Timer线程才会靠cancel()结束
// testScheduledService.cancel();
// testScheduledService.restart();
}
// 执行任务的类
public class ScheduleService extends ScheduledService<Void> {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() {
System.out.println("ScheduledService_Task begin");
//定时功能
getData();
return null;
}
};
}
}
第二步在定时任务中创建线程获取数据并更新UI,下面给出getData的详细过程:
public void getData() {
//创建线程池
ExecutorService executorService=Executors.newCachedThreadPool();
System.out.println("开始线程1");
Callable<ModBusData> callable=new GetWaterPressThread(2);
Future future=executorService.submit(callable);
try {
if(future.isDone()){
System.out.println("线程1,isNotDone");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("开始线程2");
Callable<ModBusData> callable2=new GetWaterPressThread(3);
Future future2=executorService.submit(callable2);
try {
if(future2.isDone()){
System.out.println("线程2,isNotDone");
}
} catch (Exception e) {
e.printStackTrace();
}
//关闭线程池
executorService.shutdown();
Platform.runLater(new Runnable()
{
@SneakyThrows
@Override
public void run()
{
//高频率更新UI
ModBusData modBusData1 = (ModBusData) future.get();
ModBusData modBusData2 = (ModBusData) future2.get();
updateUIData(modBusData1);
updateUIData(modBusData2);
}
});
}
重点:下面创建一个类实现 Callable,来解决向线程中传值和返回值的问题
import java.util.concurrent.Callable;
public class GetWaterPressThread implements Callable<ModBusData> {
//岗位
private Integer position;
public GetWaterPressThread(Integer position){
this.position = position;
}
@Override
public ModBusData call() throws Exception {
ModBusData modBusData = new ModBusData();
modBusData.setNo(position+"");
modBusData.setPress1(12.3f);
//模拟一秒后才能获取到数据
Thread.sleep(1000);
return modBusData;
}
}
以上为根据需求结合搜索完成的方案,其中会有一些问题,接下来还会继续学习。
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}