【问题标题】:Returning value that is changed/initialized in Thread返回在 Thread 中更改/初始化的值
【发布时间】:2013-01-18 08:42:39
【问题描述】:

在我的 j2me JAVA 应用程序中,有一个线程初始化一个对象,之后我必须通过在其他类中返回它的值来获取它。

在我调用该线程之后的主类中,我必须获取在线程中更改的值,但问题是在线程完成之前调用该函数并且它返回 null 并且程序不继续进一步。

我所做的是将返回值等待,直到布尔状态在线程内不为真,但由于该 while 循环,它挂在那里并且不会返回。

我发布下面的代码让我知道最好的解决方案,请记住此代码是在 J2me (Java) 中,即使对于线程也有有限的功能,所以不要建议我使用 Latch 或 BackgroundWorker 之类的方法,因为它在这里不起作用.

这里是hsa返回值的Thread和其他函数

public synchronized void run() {
    try {
        contacts.removeAllElements();
        pim = PIM.getInstance();
        String lists[] = pim.listPIMLists(PIM.CONTACT_LIST);
        for (int i = 0; i < lists.length; i++) {
            //code for custom backup operation
            if (customCode == 1 && i == 0) {
                continue;
            } else if (customCode == 0 && i > 0) {
                continue;
            }
            clist = (ContactList) pim.openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE, lists[i]);
            Enumeration cenum = clist.items();
            while (cenum.hasMoreElements()) {
                Contact c = (Contact) cenum.nextElement();
                ContactDTO contact = new ContactDTO();
                parseContactInfo(c, contact);
                contacts.addElement(contact);
            }
            clist.close();
        }
        readComplete = true;
    } catch (Exception e) {
    }
}

//Return contacts loaded into vector list
public ContactVector getLoadedContacts() {
    while(!readComplete){
         Thread.sleep(100);
        }
     return contacts;
}

这是我必须调用的主类

public ContactVector getContactVector() {
    DeviceContactRetriever dcr = new DeviceContactRetriever(this, language);
    dcr.start();
    ContactVector vector = dcr.getLoadedContacts();      //problem line*
    return vector;
}

所以 *problem 行在完成之前返回对象,因此它为空。

【问题讨论】:

  • readComplete - 是否声明为volatile?因为如果没有,你可能会遇到麻烦

标签: multithreading java-me jsr75


【解决方案1】:

你的问题是代码没有同步。

你需要使用wait()notify()方法,大概如下:

public synchronized void run() {
    try {
        contacts.removeAllElements();
        //...
        readComplete = true;
        this.notify();
    } catch (Exception e) {
    }
}

//Return contacts loaded into vector list
public synchronized // <-- note sync'd here
        ContactVector getLoadedContacts() {
    while(!readComplete){
         this.wait();
        }
     return contacts;
}

这是非常基本的东西,考虑学习 Java 并发教程。

如果可能,请查找 Java 5 之前的 Java 版本的教程,否则对您可以在 Java ME(目前仅限于 Java 1.3)中使用的内容的解释将与现代功能“混合”,使其更难学习与您相关的部分。

Jacob Jenkov here 为我提供了一个对我有用的示例教程,从“简介...”到“滑倒条件”包括在内的章节。请注意其他章节(“锁”和其他章节)也不错,但这些章节严重依赖自 Java 5 以来引入的功能(JSR 133 / 166 - JMM 和并发实用程序)。


对与上述错误无关的代码的几个观察。

  1. 由于您的代码相当复杂,请考虑添加日志消息以使其更易于调试 (as explained eg here)。特别是我会强烈在 catch 块中记录诸如异常之类的内容(如果您对原因感兴趣,请在网上搜索诸如 _Java 不吞下异常之类的内容),以及 lists 是否是null,如果不是,它的大小是多少,clistcenumc 是否为 null。

  2. 考虑通过将forwhile 循环内的sn-p 中的代码提取到单独的方法(如explained here)中,使您的代码更易于阅读和修改。

    李>
  3. 请注意,由于getContactVector() 中的代码可能需要很长时间才能运行,因此您最好避免从 UI 线程调用它。如果您有兴趣了解为什么会这样以及如何正确地做到这一点,请查看lcdui tag wiki 中提到的教程“网络、用户体验和线程”。

【讨论】:

  • 感谢您的回复和建议,但是返回对象的代码仍然挂起:(
  • @Saqib 测试找出它挂在哪里:1) 简化run 中的代码,以便 1) try-catch 只打印一些东西到控制台(我假设你在模拟器上测试);如果可行,那么 2) 执行 for-loop 以仅在运行时打印某些内容,将其缩小到 while 子循环中的“折叠”代码以仅打印某些内容等。添加更多日志记录以跟踪内容等
  • 嗯,它在模拟器上运行良好,在设备上却显示了我之前遇到的问题,我发现这是因为移动设备或固件。因此,考虑到您的回答是否符合我要求的目的。谢谢
猜你喜欢
  • 2017-09-03
  • 2017-02-16
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 2014-12-22
相关资源
最近更新 更多