在Java / J2ME中与UI线程交互

时间:2008-11-15 14:09:36

标签: c# java multithreading java-me ui-thread

我正在编写一个J2ME应用程序。其中一个部分定期轮询目录的内容,如果有任何新内容,则在屏幕上绘制它们。我已经通过让UI表单启动一个带有指针返回自身的轮询线程来完成此操作,并且当轮询线程找到它回调到表单并调用syncrhonized方法来更新它的显示时。这似乎工作正常。

我的问题是这个。在C#/ .NET中我知道让非UI线程更新UI并不好,处理它的正确方法是将其委托给UI线程。

E.g。以下内容:

public void DoSomeUIThing()
{
    if (this.uiComponent.InvokeRequired)
    {
        this.uiComponent.Invoke(someDelegateThatCallsBackToThis);
    }
    else
    {
        this.uiComponent.Text = "This is the update I want to happen";
    }
}

对于如何管理此流程,是否存在J2ME等效项? Java怎么样?或者Java / J2ME对此有何好处?如果没有,这是怎么做到的?

[编辑]看来Swing支持我通过SwingUtilities.invokeLater()和invokeAndWait()方法询问的内容。是否存在J2ME的等效框架?

5 个答案:

答案 0 :(得分:5)

关于Java,您所描述的内容看起来像SwingWorker (worker thread)

当Swing程序需要执行长时间运行的任务时,它通常使用一个工作线程,也称为后台线程。

Swing程序包括以下几种线程:

  • 初始线程,执行初始应用程序代码的线程。
  • 事件调度线程,其中执行所有事件处理代码。大多数与Swing框架交互的代码也必须在此线程上执行。
  • 工作线程,也称为后台线程,执行耗时的后台任务。

Single-thread rule
一旦实现了Swing组件,所有可能影响或依赖于该组件状态的代码都应该在事件派发线程中执行。

在J2EE上下文中使用时,在referencing a SwingWorker from an EJB时需要小心。

关于 J2ME ,这取决于您是将您的应用程序开发为可在任何支持MIDP的设备上运行的标准MIDlet,还是例如 RIMlet,一种基于CLDC的应用程序,使用BlackBerry特定的API,因此只能在BlackBerry设备上运行。

因为与MIDP的UI类不同,RIM类似于Swing,因为UI操作发生在事件线程上,而事件线程不像MIDP那样是线程安全的。要在事件线程上运行代码,应用程序必须获取对事件对象的锁定,或者使用invokeLater()或invokeAndWait() - 为开发人员提供额外的工作,但复杂性带有价格标签。

但对于LCDUI,您可以access a form from multiple threads

答案 1 :(得分:4)

Java ME有很多个人资料。如果您的意思是MIDP,那么Display.runSerially就是您想要的。

对于AWT(Swing),您将使用EventQueue.invokeLaterSwingUtilities.invokeLater只是必需的,因为Java 1.1没有EventQueue方法 - 1.2即将庆祝其十岁生日)。对于Common DOM API,请使用DOMService.invokeLater

无论GUI API如何声称线程安全,它们可能都是错误的(在JDK7中删除了一些Swing的声明,因为它们不可实现)。在任何情况下,应用程序代码都不太可能是线程安全的。

答案 2 :(得分:1)

对于j2me应用程序,您可能希望保持简单。主要的是仅在事件线程中触摸UI组件。这样做的直接方法是使用invokeLater or invokeAndWait。根据您的库,您将无法访问除此之外的任何内容。一般情况下,如果您的平台没有提供这些,它可能等同于没有线程支持而不是问题。例如the blackberry does support it

答案 3 :(得分:1)

如果在SWT下开发,则可以通过Display对象的asyncExec()方法实现。您传递实现Runnable的对象,以便UI线程执行在其他线程中完成的更改。

这是借鉴here

的一个例子
public void itemRemoved(final ModelEvent me)
{
   final TableViewer tableViewer = this.viewer;

   if (tableViewer != null)
   {
      display.asyncExec(new Runnable()
      {
         public void run()
         {
            tableViewer.remove(me.getItem());
         }
      }
   }
}

答案 4 :(得分:1)

我可以证明MIDP UI工具包确实是线程安全的,因为我在大多数制造商生产的数百万部手机上都运行了大型的带有复杂GUI的MIDlet,而且我从未见过这方面的问题。