预定线程池完成后,更改JButton的文本

时间:2019-02-17 22:44:51

标签: java swing

我有一个程序,当按我的GUI上的按钮时,可以打开RFID阅读器。这一切都很好。一段时间后,我使用ScheduledThreadPool关闭RFID阅读器,如下所示:

Executors.newScheduledThreadPool(1).schedule(() -> {
        try {
            phid1.close();
            phid2.close();
        } catch (PhidgetException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        WalletLocatorInterface.infoTextArea.append("\nClosed RFIDs\n\n");
        WalletLocatorInterface.infoTextArea.append("Final Wallet Locations:\n");          
        try {
            getLocations();
        } catch (SQLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        WalletLocatorInterface.trackingButton.setText("Start Tracking"); // this does not change the text on the button
    }, TimeOptionWindow.getTime(), TimeUnit.SECONDS);

一旦按下GUI界面上的Jbutton,按钮上的文本将更改为“ Tracking ...”,但是该线程已结束,我想将文本更改回“ Start Tracking”。

但是,由于按钮上的文字没有变回来,所以我遇到了困难。有谁知道我该如何解决?甚至有可能吗?谢谢。

1 个答案:

答案 0 :(得分:0)

仅在用户界面线程中访问小部件

WalletLocatorInterface.trackingButton.setText("Start Tracking"); // this does not change the text on the button 

从不 与另一个线程中的Swing小部件进行交互。学习Concurrency in Swing上的Oracle教程。您有时可能会放弃它,或者可能在运行时使您的应用程序发生可怕的事情。

保持执行者身份

Executors.newScheduledThreadPool(1).schedule( 

不要在每次执行任务时实例化线程池和执行程序。保持执行者在身边。在大多数情况下,您可能希望在整个应用程序运行期间都保留相同的执行程序对象。每次有工作要做时,重复调用执行者的schedule方法。根据需要,考虑在池中使用多个线程而不是一个。

每次调用Executors.newScheduledThreadPool(1)时,您将使用另一个线程池(一个线程)实例化另一个执行程序。这样做三遍,您将拥有三个执行器,每个执行器带有一个单线程池,总共三个线程。而是实例化由三个线程的单个线程池支持的执行程序。然后向该执行者提交一系列任务。提交的任务将在三个线程中的任何一个上运行,因为这是执行程序的工作:将任务分配给线程。

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool​​( 3 ) ; // Keep around a reference to this executor service.
… // Do some other stuff
scheduledExecutorService.schedule( () -> { System.out.println( "Eat early breakfast." ) } , … ) ;
… // Do some other stuff
int snacksCount = 3 ;
for( int i = 1 ; i <= snacksCount ; I ++ ) {
   scheduledExecutorService.schedule( () -> { System.out.println( "Eat snack." ) }  , … ) ;
}
… // Do some other stuff
scheduledExecutorService.schedule( () -> { System.out.println( "Eat lunch." ) }  , … ) ;
… // Do some other stuff
scheduledExecutorService.schedule( () -> { System.out.println( "Eat dinner." ) }  , … ) ;
… // Do some other stuff
scheduledExecutorService.shutdown() ;  // Always shut down your executor service. Otherwise, its pool of threads may continue indefinitely, even beyond the run of your app. 

重要:请注意,如果有多个线程在运行,则计划任务可能无法按提交的顺序执行。例如,晚餐可以在午餐前吃。如果顺序很重要,请使用单线程池。

如果您出于这个原因确实使用了单线程池,请通过调用Executors.newSingleThreadScheduledExecutor()而不是Executors.newScheduledThreadPool(1)来使代码更具自记录性,如您的Question所示。使用带池大小参数的变体向阅读程序员建议,她可以稍后在编辑代码时灵活地更改该参数。当然,也可以在代码注释中以散文形式进行解释。

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ; // *Must* use only a *single* thread pool, to ensure our meal-eating tasks execute in the order they were submitted. 

仅供参考:并行编程非常棘手。最后,我建议您阅读Java Concurrency in Practice 由Brian Goetz等人撰写。