【问题标题】:Use parameters passed into event listener by background thread on Main thread在主线程上使用后台线程传递给事件监听器的参数
【发布时间】:2018-07-23 22:50:21
【问题描述】:

假设我有一个这种形式的类。

class TestClass implements SomeInterface {

    Data myData;

    public TestClass() {
    }

    @Override
    public void onData(Data data) {
        // do stuff with data
        myData = data
    }
}

其中SomeInterface 在后台线程上进行一些数据处理并调用onData,后者也在后台线程上运行。我希望能够在Main 线程上使用onData 返回的数据(更新UI,在主线程上执行其他操作等),因为我确切知道调用后台线程onData 后的时间将被调用。由于我使用的是某个库中的SomeInterface,因此我无法修改此功能(我并没有完全按照预期使用它)。

在 Android 中我会做一些事情 like this 但我显然不能在纯 Java 应用程序中这样做,因为没有 Looper 这样的事情。从后台线程设置实例变量也不允许我从主线程访问它。

【问题讨论】:

  • 如果你使用AWT或者swing,那么使用EventQueue.invokeLater(Runnable)
  • 看看SwingWorker,这对于Java来说基本上是一样的。 docs.oracle.com/javase/10/docs/api/javax/swing/SwingWorker.html 请注意,无论是 Android 还是 Java 桌面,主线程都不会更新 gui。
  • 什么GUI框架?例如,Swing 提供了SwingWorkerSwingUtilities.invokeLater,它们为您提供了将执行移至主线程的方法
  • 我没有使用 Swing、AWT 或任何 UI 库。我只是以更新 UI 为例。
  • 如果不是 Swing 或 AWT,它是什么 UI?

标签: java multithreading


【解决方案1】:

您可以发明自己的框架,但这有点愚蠢。 ExecutorServicejava.util.concurrent 的其他类基本上只需要一点组装就可以为您完成所有这些工作。

这里我在主线程上创建了一些输入数据,通过使用Callable 接口和执行器将其传递给后台线程。然后主线程使用Future 对象从后台线程获取输出数据。轻松愉快。

public abstract class SimpleBackgroundService {

   public static void main( String[] args ) throws InterruptedException, ExecutionException {

      final InputData input = new InputData( 123, "Hi Mom" ); // really should be immutable

      Callable<OutputData> task = new Callable<OutputData>() {
         private final InputData taskInput = input;
         @Override
         public OutputData call() {
            return new OutputData( taskInput );
         }
      };

      ExecutorService es = Executors.newFixedThreadPool( 1 );
      Future<OutputData> taskOutput = es.submit( task );
      // do some stuff here while the task completes.
      OutputData data = taskOutput.get();  // will block and wait if needed
      System.out.println( data );
   }

   static class InputData {

      private final int num;
      private final String msg;

      public InputData( int num, String msg ) {
         this.num = num;
         this.msg = msg;
      }

   }
   static class OutputData {

      private final int num2;
      private final String msg2;

      public OutputData( InputData dat ) {
         num2 = dat.num;
         msg2 = dat.msg;
      }
   }

}

【讨论】:

  • 谢谢,但不幸的是我没有调用任务本身的奢侈。我只是从某个 jar 中订阅了一个事件侦听器,该 jar 调用了我的类上的处理程序
  • 你应该从一开始就提到这一点。你真的不容易回答这个问题,是吗?把完整的信息放在OP中,也许有人会回答。
  • 我相信我在 OP 中说过我不能修改库的功能
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多