J2ME -如何使线程返回一个值,并在该线程完成后,在其他操作中使用返回值



我有一些关于线程使用的问题,特别是当你必须等待一个线程完成以便你可以执行其他操作时。

在我的应用程序中,我使用线程的操作,如http连接或当我读取或写入RecordStore。

例如,在下面用来初始化线程的类中,我使用名为HttpQueryCustomers的方法从web服务检索一些客户。
    public class thrLoadCustomers implements Runnable {
    private RMSCustomer mRMSCustomer;    
    private String mUrl;
    public thrLoadCustomers(RMSCustomer rmsCust, String url) {        
        mRMSCustomer = rmsCust;        
        mUrl = url;
    }
    public void run() {
        String jsonResultados = "";
        try {
            jsonResultados = HttpQueryCustomers();
        } catch (IOException ex) {
            //How to show a message from here??
        } catch (SecurityException se) {
             //How to show a message here??
        } catch (NullPointerException npe) {
             //How to show a message from here??
        }
        if (!jsonResultados.equals("")) {
            try {
                mRMSCustomer.save(jsonResultados);
            } catch (RecordStoreException ex) {
               //How to show a message from here???
            }
        }
    }
    public String HttpQueryCustomers() throws IOException,SecurityException,NullPointerException {
        StringBuffer stringBuffer = new StringBuffer();
        HttpConnection hc = null;
        InputStream is = null;
        System.out.println(mUrl);
        try {
            hc = (HttpConnection) Connector.open(mUrl);
            if (hc.getResponseCode() == HttpConnection.HTTP_OK) {
                is = hc.openInputStream();
                int ch;
                while ((ch = is.read()) != -1) {
                    stringBuffer.append((char) ch);
                }
            }
        } finally {
            is.close();
            hc.close();
        }
        String jsonData = stringBuffer.toString();
        return jsonData.toString();
    }
}
注意,在上面的类中,我传递了一个名为rmsCust的参数,类型为RMSCustomer

RMSCustomer是我用来处理与RMS相关的所有操作的类:

public class RMSCustomer {
    private String mRecordStoreName;
    private Customer[] mCustomerList;
    public RMSCustomer(String recordStoreName) {
        mRecordStoreName = recordStoreName;
    }
    public Customer[] getCustomers() {
        return mCustomerList;
    }
    public Customer get(int index) {
        return mCustomerList[index];
    }  
    public void save(String data) throws RecordStoreException,JSONException,NullPointerException {
        RecordStore rs = null;
        int idNuevoRegistro;
        String stringJSON;
        try {
            rs = RecordStore.openRecordStore(mRecordStoreName, true);
            JSONArray js = new JSONArray(data); 
            //Set the size of the array
            mCustomerList = new Customer[js.length()];
            for (int i = 0; i < js.length(); i++) {
                JSONObject jsObj = js.getJSONObject(i);
                stringJSON = jsObj.toString();                   
                idNuevoRegistro = addRecord(stringJSON, rs); 
                //Add a new Customer to the array
                mCustomerList[i] = initializeCustomer(stringJSON, idNuevoRegistro);
            }

        } finally {
            if (rs != null) {
                rs.closeRecordStore();
            }
        }
    }
    public int addRecord(String stringJSON, RecordStore rs) throws JSONException,RecordStoreException {                    
        byte[] raw = stringJSON.getBytes();
        int idNuevoRegistro = rs.addRecord(raw, 0, raw.length);
        return idNuevoRegistro;             
    }   
    public Customer initializeCustomer(String stringJSON, int idRecord) throws JSONException {
        Customer c = new Customer();
        JSONObject jsonObj = new JSONObject(stringJSON);
        // Set Customer properties 
        //...
        return c;
    }

}

该类用于显示客户列表,正如您所看到的,它扩展了 list 类并接收客户数组作为参数。

public class ListCustomers extends List {
    private final Customer[] mData;
    public static ListCustomers create(Customer[] data) {
        int i = 0;
        for (; i < data.length; i++) {
            if (data[i] == null) {
                break;
            }
        }
        String[] names = new String[i];
        for (int j = 0; j < i; j++) {
            names[j] = data[j].name;
        }
        return new ListCustomers(names, data);
    }
    protected ListCustomers(String names[], Customer[] data) {
        super("List of Customer", IMPLICIT, names, null);
        mData = data;
    }
    public Customer getSelectedObject() {
        return mData[this.getSelectedIndex()];
    }
}

最后当我想显示客户列表时,这是我如何从MIDlet调用线程(使用所有前面的3个类):

private void showCustomerList(String url) {
        showWaitForm();
        if (scrCustomerList == null) {            
            rmsCustomers = new RMSCustomer("rmsCustomers");          
            thrLoadCustomers load = new thrLoadCustomers(rmsCustomers, url);
            Thread t = new Thread(load);
            t.start();
            try {
                t.join();
            } catch (InterruptedException ex) {
            }
            scrCustomerList = ListCustomers.create(rmsCustomers.getCustomers());
            scrCustomerList.addCommand(cmdSelect);
            scrCustomerList.addCommand(cmdBack);
            scrCustomerList.setCommandListener(this);
        }
        mDisplay.setCurrent(scrCustomerList);
    }

现在我的问题是:

  1. showWaitForm()不工作(它设置了一个表单与测量作为目前的形式)
  2. 我不知道如何显示所有可能被抛出的异常在thrLoadCustomers类中
  3. 我不知道使用t.join()是否是最好的选择
  4. 最后一个问题是关于我正在读的一本书所说的:
特别是线程,可能是一种稀缺商品。MSA的规范要求必须允许应用程序创建<<strong> 10个线程/strong>。你能做并不意味着你应该做。一般来说,尽量使用最少的资源,这样您的应用程序就可以尽量平稳运行

这是第一次使用线程,在我的应用程序中,我可能有多达10个线程(类)。然而,我一次只执行一个线程,我是否违背了前面的报价??

我希望我没有问太多问题。非常感谢您的帮助。

p。如果没有Gregor Ophey

的帮助,我在这里发布的大部分代码是不可能的。

问题#1是关于与线程无关的另一个问题,并且显示的代码很少。我建议你发布一个新的专用问题,对这个问题进行适当的解释。

问题#2和#3:您可以这样定义包装器类:

    public class WSResult {
        private boolean success; //true if the WS call went ok, false otherwise
        private String errorMessage; //Error message to display if the WS call failed.
        private Object result; //Result, only if the WS  call succeeded.
        private boolean completed = false;
        //TODO getter and setters methods here
    }

在您的屏幕中,您可以创建一个result实例并等待它:

    WSResult result = new WSResult();
    //Start thread here
    new Thread(new LoadCustomersTask(result)).start();
    //This is old school thread sync. 
    synchronized(result){
        while(!result.isCompleted()){
            result.wait();
        }
    }
    //Here the thread has returned, and we can diaplay the error message if any
    if(result.isSuccess()){
    } else {
        //Display result.getErrorMessage()
    }

那么你的可运行文件应该是这样的:

    class LoadCustomersTask implements Runnable {
        private final WSResult result;
        public LoadCustomersTask(WSResult res){
            result = res;
        }
        public void run(){
            //Do the WS call
            //If it went well
            result.setSuccess(true);
            result.setResult(jsonResultados);
            //Else
            result.setSuccess(false);
            result.setErrorMessage("Your error message");

            //In any case, mark as completed
            result.setcompleted(true);
            //And notify awaiting threads           
            synchronized(result){
                result.notifyAll();
            }       
        }
    }

你也可以用线程来做。Join,但是wait/notify更好,因为您不会使屏幕依赖于运行可运行程序的特定线程。您可以在结果实例上等待/通知,如所示,或者在可运行实例上等待/通知,如果它只用于一次使用。

问题#4:是的,线程不能被滥用,特别是在java中,程序通常在单核cpu中运行,频率在MHz数量级。尽量不要同时运行超过1-3个线程。如果你真的需要,考虑使用一个线程来运行所有后台任务(阻塞队列)。

最新更新