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

     2023-02-23     39

关键词:

【中文标题】J2ME - 如何使线程返回一个值,并在该线程完成后,在其他操作中使用返回值?【英文标题】:J2ME - How to make a thread return a value and after that thread is finished, use the return value in other operations? 【发布时间】:2014-06-23 01:14:58 【问题描述】:

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

在我的应用程序中,我使用线程进行诸如 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);
    

现在这是我遇到的问题:

    showWaitForm() 不起作用(它设置了一个带有 Gauge 的表单作为 当前表格) 我不知道如何显示所有可能引发的异常 在 thrLoadCustomers 类中。 不知道用t.join()是不是最好的选择 最后一个问题是关于book I'm reading 所说的:

线程尤其是稀缺商品。 MSA 规范要求必须允许应用程序创建 十个线程。仅仅因为你可以并不意味着你应该。一般来说, 尝试使用尽可能少的资源,以便您的应用程序将 尽可能顺利地运行

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

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

P.D 我在此处发布的大部分代码在 Gregor Ophey 的帮助下是不可能实现的

【问题讨论】:

J2ME 有 Future 和 Callable 吗?我要么向后移植这些概念,要么重新实现这些概念。 @DavidEhrmann 这些类不可用,我建议不要尝试编写 DIY 替代代码,除非您在并发编程方面非常有经验。 @MisterSmith 这些类的源代码可用。 【参考方案1】:

问题 #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
    

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

    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()
    

那么你的runnable会是这样的:

    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();
                   
        
    

您也可以使用 thread.join 执行此操作,但等待/通知更好,因为您不会使屏幕依赖于 runnable 运行的特定线程。您可以在结果实例上等待/通知,如图所示,或者在 runnable 上等待/通知(如果它是供一次性使用的)。

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

【讨论】:

拜托,你能给我解释一下这几行吗:synchronized(result)result.wait() 在我的回答中,我使用Object.wait/Object.notify 而不是Thread.sleep/Thread.interrupt 来协调线程。您可以阅读here 了解有关差异的更多信息,但想法是相同的:一个线程等待第二个线程完成。调用 wait/notify 时需要同步块,否则会抛出异常。 非常感谢@Mister Smith 我按照你的建议做了,现在我的代码更有条理了。

如何在python中启动一个线程池并在一个线程完成时停止?

】如何在python中启动一个线程池并在一个线程完成时停止?【英文标题】:Howtostartapoolofthreadsandstopwhenoneisfinishedinpython?【发布时间】:2022-01-1921:06:28【问题描述】:我正在尝试编写一个同时发送多个请求并返回第一个响应的函数... 查看详情

如何使用 Platform.runLater 使 JavaFX 线程安全

】如何使用Platform.runLater使JavaFX线程安全【英文标题】:HowtomakeJavaFXthread-safewithPlatform.runLater【发布时间】:2014-12-1714:50:51【问题描述】:我正在制作一个JavaFX应用程序,在该应用程序中读取问题并在按下开始按钮时生成解决方... 查看详情

从线程返回值

...valuefromthread【发布时间】:2010-12-2513:24:27【问题描述】:如何让线程将元组或我选择的任何值返回给Python中的父级?【问题讨论】:【参考方案1】:我建议您在启动线程之前实例化一个Queue.Queue,并将其作为线程的参数之一传递... 查看详情

命令不在 J2me 的单独线程中工作

】命令不在J2me的单独线程中工作【英文标题】:CommandNotworkinginseparatethreadinJ2me【发布时间】:2010-04-2513:26:39【问题描述】:我正在创建一个蓝牙应用程序。我使用退出命令创建了一个简单的midlet,并创建了一个用于查找服务和... 查看详情

当 AsyncTask 完成时返回一个值

...我也知道我可以使用get()使AsyncTask同步,但我不想阻塞UI线程。我使用AsyncTask和OkHttp上传文件并得到如下结果:staticclassUploadFileexten 查看详情

如何使“主线程”等待“子线程”执行结束后再继续执行

参考技术A主线程抛出一个子线程异步处理一些东西,这时主线程要等待子线程运行完成再完成(其实我是为了统计运行时间的)。这里抛出的子线程可能递归的调用自己,就是再抛一个他的子线程出来,但是到底一共抛多少,... 查看详情

如何在另一个线程中关闭 MFC 模态对话框并获得对话框返回值?

】如何在另一个线程中关闭MFC模态对话框并获得对话框返回值?【英文标题】:HowdoIcloseaMFCModalDialoginanotherthreadandcangetthedialogreturnvalue?【发布时间】:2019-06-1908:42:02【问题描述】:我有一个MFC对话框项目。主对话框中有一个下载... 查看详情

如何导入while循环并使用多线程返回其更新值?

】如何导入while循环并使用多线程返回其更新值?【英文标题】:Howtoimportawhileloopandreturnitsupdatedvaluewithmulti-threading?【发布时间】:2022-01-2018:46:58【问题描述】:如何导入while循环并使用多线程返回其更新值?想法如下,但我不知... 查看详情

如何使用线程去执行一个有返回值的方法,并获取返回值?

这个问题有点奇怪。。。一般情况需要用线程的话都是异步的,如果是需要等待返回值做处理的情况大部分都是同步的不需要用到多线程(除非是响应式,即线程执行完了,然后促发某个方法来处理某个结果),这种情况的话最好... 查看详情

python多线程-semaphore(信号对象)

...。计数器永远不会低于零,当acquire()发现计数器为零时,线程阻塞,等待其他线程调用release()。Semaphore对象支持上下文管理协议。方法:acquire(blocking=True,timeout=None)获取信号。当blocking=True时:如果调用时计数器大于零,则将其减... 查看详情

如何从线程中获取返回值?

】如何从线程中获取返回值?【英文标题】:Howtogetareturnvaluefromathread?【发布时间】:2019-09-0606:31:14【问题描述】:让我们说一个函数,intfun()staticinta=10;a=a+1;returna;上面的函数返回一个整数值,//Withoutthreadobtainingreturnvalue#include<... 查看详情

线程中的future

allable相当于Runnable,所以,这里实现的是一个线程,但是与Runnable不同的是,它是具有返回值的,这个返回值就是我们想要任务返回的结果,比如说,我们想要任务返回的是一个提示信息,那么,返回值可以是String,然后在我们要... 查看详情

如何使进程与随机数量的活动线程同步?

】如何使进程与随机数量的活动线程同步?【英文标题】:Howtosynchronizeaprocesswithrandomnumberofactivethreads?【发布时间】:2019-05-1818:51:11【问题描述】:我有以下问题。我的进程产生了4个线程,它们独立执行相同的任务,需要等待所... 查看详情

如何使线程超时

】如何使线程超时【英文标题】:Howtotimeoutathread【发布时间】:2011-01-1712:59:27【问题描述】:我想运行一个线程一段固定的时间。如果它没有在那段时间内完成,我想杀死它,抛出一些异常,或者以某种方式处理它。怎么办?... 查看详情

从线程运行函数时如何返回值[重复]

】从线程运行函数时如何返回值[重复]【英文标题】:HowwouldIreturnavaluewhilerunningafunctionfromathread[duplicate]【发布时间】:2020-09-2501:08:47【问题描述】:使用std#include如果我想让线程运行它,我将如何返回一个值?例如include<iostream... 查看详情

如何终止包装函数的线程? [复制]

】如何终止包装函数的线程?[复制]【英文标题】:HowtoterminateaThreadthatwrapsafunction?[duplicate]【发布时间】:2015-03-2314:48:29【问题描述】:我正在做关于线程的课程练习。我的问题是如何在函数完成时终止包装函数的线程(并获得... 查看详情

在后台线程执行硬任务,在主线程返回结果

...找一个开发人员友好的解决方案(不向项目添加依赖项)如何在后台线程中执行一些硬任务,并在任务完成后将结果返回到主线程。我找到了允许这样做的“AsyncTask”。但是要使用它,您需要为需要在后 查看详情

如何从python中的线程获取返回值?

】如何从python中的线程获取返回值?【英文标题】:Howtogetthereturnvaluefromathreadinpython?【发布时间】:2011-10-1703:54:05【问题描述】:下面的函数foo返回一个字符串\'foo\'。如何获取线程目标返回的值\'foo\'?fromthreadingimportThreaddeffoo(ba... 查看详情