Discussion Board

Results 1 to 11 of 11
  1. #1
    Registered User
    Join Date
    Jun 2014
    Posts
    12

    Question Make a thread return a value and after the thread is finished, use the return value

    Hi
    I got some questions regarding the use of threads, specially when you have to wait for a thread to be finished so you can perform other operations.

    In my app, I use threads for operations such as http connections or when I read from or write to a RecordStore.

    For example in the following class that I use to initialize my thread, I retrieve some customers from a webservice using the method called HttpQueryCustomers.

    Code:
        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();
        }
    }
    Notice in the above class that I pass a parameter called rmsCust of the type RMSCustomer

    RMSCustomer is a class that I use to handle all the operations related to RMS:

    Code:
    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;
        }
    
    
    }
    This class is used to show a list of customer and ,as you can see, it extends the List class and receives an array of Customers as a parameter.

    Code:
    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()];
        }
    }
    Finally this is how I call the thread from the MIDlet (using all the 3 previous classes) when I want to show a List of Customers:

    Code:
    private void showCustomerList(String url) {
            showWaitForm(); //This doesn't work
            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);
        }
    Now here's the problems I have :

    1. The showWaitForm() doesn't work (it sets a form with a Gauge as the Current form) I noticed that it only works when I call threads but don't use join()
    2. I don't know how to show all the exceptions that might be thrown from within the thrLoadCustomers class.
    3. I don't know whether using t.join() is the best choice when I need to wait for a thread to be finished.
    4. The last question is about something the book I'm reading says :

    Threads, in particular, can be a scarce commodity. The MSA specification requires that an application must be allowed to create ten threads. Just because you can doesn’t mean you should. In general, try to use the fewest resources possible so that your application will run as smoothly as possible
    This is the first time a use threads, and in my app I might have up to 10 threads (classes). However, I will only execute once thread at the time, will I be going against what the previous quotation says??

    I hope I'm not asking too many questions. Thank you very much for your help.

  2. #2
    Nokia Developer Champion
    Join Date
    Feb 2009
    Location
    Noida, India
    Posts
    3,087

    Re: Make a thread return a value and after the thread is finished, use the return val

    Instead of join(), add a Boolean variable done in your thread class - set it false start the start of the thread and set it true once the required process of the thread is complete.

    Thread t = new Thread(load);
    t.start();
    // to wait for the thread to complete its job try this

    While(!t.done) {
    this.sleep(500); // will wait for 500 ms everytime before checking if Thread is done.
    }

    }
    You can define any no. of threads in your project, but keep limited no. of threading running together.
    thanks,
    ~Amitabh
    (Champion of the Month -Aug'13)
    Follow me on my blog for Innovative Mobile Apps

  3. #3
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,798

    Re: Make a thread return a value and after the thread is finished, use the return val

    I have not read the complete thing, but there are two things here:
    - despite to its apparently simple nature, a Midlet follows an asynchronous, event-driven programming model. In this model you generally should not join in the UI thread, or wait in a loop, but allow control returning to the dispatcher, so other events can be handled
    - GUI environments usually do not really like when secondary threads try to access the GUI
    In case of a Midlet with LCDUI, lcdui.Display.callSerially(Runnable r), http://docs.oracle.com/javame/config...lang.Runnable) is what you want to use, and if you switch to LWUIT, lwuit.Display has https://lwuit.java.net/javadocs/com/...lang.Runnable) that method too (and some extras).
    Just as an interesting detail: Android has similar mechanism, Activity.runOnUiThread(Runnable r), which is a bit more self-explaining than the Java ME variant.

  4. #4
    Nokia Developer Champion
    Join Date
    Mar 2013
    Posts
    686

    Re: Make a thread return a value and after the thread is finished, use the return val

    I have also not read the entire code (but did read the post text)
    1. My recommendation is to not use join() and not use wait() loop on Boolean but rather use callbacks/listeners that will transmit back to you when a thread finished successful or caught an exception.
    2. I didn't exactly understand what you mean by show the exception, do you mean show them on the UI? if so use the same listener/callback mechanism (also you can catch all the exception by just catch the top level object Exception
    3. answered in 1
    4. it means concurrent threads not sequential so you are ok.
    Heard of DVLUP? Join here

  5. #5
    Nokia Developer Champion
    Join Date
    Feb 2009
    Location
    Noida, India
    Posts
    3,087

    Re: Make a thread return a value and after the thread is finished, use the return val

    I missed showing the exceptions from the thread - on the UI, for this also you can have a public Variable Msg - which you can assign in the thread and render on the UI screen as Status while the thread is running.
    While(!t.done) {
    this.sleep(500); // will wait for 500 ms everytime before checking if Thread is done.
    // display Msg
    }
    I have even used in my project to show the status of say things like upload or download of file/content or RMS updates or Sync process.
    thanks,
    ~Amitabh
    (Champion of the Month -Aug'13)
    Follow me on my blog for Innovative Mobile Apps

  6. #6
    Registered User
    Join Date
    Jun 2014
    Posts
    12

    Re: Make a thread return a value and after the thread is finished, use the return val

    Now I'm a little confused, should I or shouldn't I use a wait() loop on a Boolean??
    I think I know how to implement this, but regarding the other possibilities about using lcdui.Display.callSerially or callbacks, do you think you could provide an example? I have searched but I have found anything, so I'd really appreciate it if you could share a example.

    Thanks again.

  7. #7
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,798

    Re: Make a thread return a value and after the thread is finished, use the return val

    showWaitForm probably has problems because the dispatcher can not render anything, since a join is waiting instead.
    I could imagine something like
    Code:
    private void showCustomerList(String url) {
            showWaitForm(); //This will hopefully work afterwards
            if (scrCustomerList == null) {
                rmsCustomers = new RMSCustomer("rmsCustomers");          
                final thrLoadCustomers load = new thrLoadCustomers(rmsCustomers, url);
                final Midlet diz=this;
                new Thread(new Runnable() {
                    public void run() {
                        load.run();
                        Display.getDisplay(diz).callSerially(new Runnable() {
                            public void run() {
                            scrCustomerList = ListCustomers.create(rmsCustomers.getCustomers());
                            scrCustomerList.addCommand(cmdSelect);
                            scrCustomerList.addCommand(cmdBack);
                            scrCustomerList.setCommandListener(diz);
                            mDisplay.setCurrent(scrCustomerList);
                    }}); // callSerially
                }}).start(); // Thread
            }
            else mDisplay.setCurrent(scrCustomerList);
        }
    I am not entirely sure if it works, but the pattern is that the thread does the loading as it was doing so far, and at the end it calls back the UI, creating the list on the UI thread. You can of course experiment with all kind of things, like leaving out the callSerially thing, and create+setCurrent the list in the thread, just to see what happens. If it does not work (I guess it should not), it may be still enough to wrap the setCurrent part only, so creating the List may actually work in a thread.
    Also, the showWaitForm line could be moved inside the if-block, otherwise the setCurrent-line in the else will replace its effect immediately.
    Last edited by wizard_hu_; 2014-06-27 at 13:09. Reason: while typing a response, I noticed that I forgot starting the Thread

  8. #8
    Registered User
    Join Date
    Jun 2014
    Posts
    7

    Re: Make a thread return a value and after the thread is finished, use the return val

    Hi shai.i.
    I was about to open a new thread with a similar question, but since you mentioned what I was going to ask, I decided to ask my questions here.
    I hope you can help me.
    Quote Originally Posted by shai.i View Post
    I have also not read the entire code (but did read the post text)
    1. My recommendation is to not use join() and not use wait() loop on Boolean but rather use callbacks/listeners that will transmit back to you when a thread finished successful or caught an exception.
    How would they transmit back when the thread is finished or an exception is thrown?? I was thinking in creating a wrapper class something like this :

    Code:
    public class WSResult {
            private boolean success; 
            private String errorMessage; 
            private Object result; 
            private boolean completed = false;
    
        }
    But I'm still not sure, so it's be great if you could give us an example of how would you implement the callback/listener
    Quote Originally Posted by shai.i View Post
    2. I didn't exactly understand what you mean by show the exception, do you mean show them on the UI? if so use the same listener/callback mechanism (also you can catch all the exception by just catch the top level object Exception
    I'm really new to Java, but I think I read somewhere that is always better to catch specific exceptions rather than general exceptions.

  9. #9
    Registered User
    Join Date
    Jun 2014
    Posts
    12

    Re: Make a thread return a value and after the thread is finished, use the return val

    Quote Originally Posted by wizard_hu_ View Post
    showWaitForm probably has problems because the dispatcher can not render anything, since a join is waiting instead.
    I could imagine something like
    Code:
    private void showCustomerList(String url) {
            showWaitForm(); //This will hopefully work afterwards
            if (scrCustomerList == null) {
                rmsCustomers = new RMSCustomer("rmsCustomers");          
                final thrLoadCustomers load = new thrLoadCustomers(rmsCustomers, url);
                final Midlet diz=this;
                new Thread(new Runnable() {
                    public void run() {
                        load.run();
                        Display.getDisplay(diz).callSerially(new Runnable() {
                            public void run() {
                            scrCustomerList = ListCustomers.create(rmsCustomers.getCustomers());
                            scrCustomerList.addCommand(cmdSelect);
                            scrCustomerList.addCommand(cmdBack);
                            scrCustomerList.setCommandListener(diz);
                            mDisplay.setCurrent(scrCustomerList);
                    }}); // callSerially
                }}).start(); // Thread
            }
            else mDisplay.setCurrent(scrCustomerList);
        }
    wizard_hu_ wow I must admit that at first it scared me to see so many run() 's in so little code, but now I think I got it:
    You put both the execution of the thread that brings the data from the webservice(thrLoadCustomers ) and the rest of the code that displays the list of customers in a "anonymous" thread so that is guaranteed that the second part will be run once the first part , load.run(), is done. Am I right?

    Just a couple more questions :

    1. If had to say in a few word what exactly callSerially does, how would you explain it?
    2. If an exception was thrown inside the thrLoadCustomers how would you show a message to the user? I was thinking in having a wrapper class, just like eddy17 mentioned ,and add an object of this class as a property of the thread so that once the thread is done running, I could check that object and see whether the execution was successful or not (exception) in which case I could pull the exception message from the "errorMessage" of the object. What do you think about this approach?



    Quote Originally Posted by wizard_hu_ View Post
    You can of course experiment with all kind of things, like leaving out the callSerially thing, and create+setCurrent the list in the thread, just to see what happens.
    I think there's a typo here, what did you want to write?

    Thanks again wizard_hu_ for taking the time to help me (Y)
    Last edited by wizard_hu_; 2014-06-27 at 13:08. Reason: EDIT by wizard_hu_: while typing a response, I noticed that I forgot starting the Thread

  10. #10
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,798

    Re: Make a thread return a value and after the thread is finished, use the return val

    EDIT: sorry, this one goes for Eddy17, just #9 has not been here when I opened the tab.

    Yes, your approach is viable. Exception is just a kind of result, and whatever communication pattern you use, you can always pass an Exception or an error String too. The only thing is that you have to catch it in the thread, and explicitly pass it back to the UI yourself. If the pass-value-back-to-UI code dies, that is indeed a problem, but in that case it is probably safe to assume that the entire Midlet will go down pretty soon... For simple checks, Thread.isAlive can be used too, if a thread has died without providing results, one may suspect that something gone wrong.
    It is a matter of taste what you pass back, but if you prefer passing an Object (and checking its actual type later), it may be enough alone: if it is a String, there is some problem (success and completed are both considered false), if it is a SomethingElse, everything is fine and that is the result. Or have two fields, String and SomethingElse: if String is not null, then there is a problem and SomethingElse is either null, or maybe contains some partial result; if String is null, everything is fine and SomethingElse is the complete result.

  11. #11
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,798

    Re: Make a thread return a value and after the thread is finished, use the return val

    Ehm, look for the red .start() edited into the previous messages, the Thread object does not do anything without it.
    Quote Originally Posted by axel96_41 View Post
    wizard_hu_ wow I must admit that at first it scared me to see so many run() 's in so little code
    Yep, at the first attempt I forgot them completely, and just wrote new Runnable(){code lines here}, just there are no such delegates in Java, so the run(){} is necessary.
    , but now I think I got it:
    You put both the execution of the thread that brings the data from the webservice(thrLoadCustomers ) and the rest of the code that displays the list of customers in a "anonymous" thread so that is guaranteed that the second part will be run once the first part , load.run(), is done. Am I right?
    Yes, something like that. The outer thing is an anonymous thread with 2 lines of code, the new Thread(new Runnable(){public void run(){thread code here}}).start() would be that. Unfortunately I forgot the start now as I look back, I will put it there in a couple minutes, with a different color. This thread executes load.run() and the callSerially(), in this order, no magic here, just 2 consecutive lines of code.
    The other Runnable is not a thread, that is just a wrapping for the UI-related code, which is passed to the UI thread using callSerially. http://docs.oracle.com/javame/config...lang.Runnable) describes it. In short: the event loop likes handling one event at a time, like handling a button press calls your event handler, and until your event handler returns, nothing else happens in the event dispatcher, it is a simple, synchronous method call. This way there will not be half-handled events, thus multiple event handlers working with the same resource (let it be the drawing on the display, or handling files, RMS, etc) will not interfere with each other. callSerially simply puts the passed code into the event queue, and it is going to be called later, so it will not clash with other things drawing on the screen either.
    If an exception was thrown inside the thrLoadCustomers how would you show a message to the user? I was thinking in having a wrapper class, just like eddy17 mentioned ,and add an object of this class as a property of the thread so that once the thread is done running, I could check that object and see whether the execution was successful or not (exception) in which case I could pull the exception message from the "errorMessage" of the object. What do you think about this approach?
    Yes, Eddy17's approach can be used, Exception-s, result String-s are no different from other type of data.
    The only trick here is what happens to "Midlet diz": variables have to be final to be accessible from in-line anonymous object implementations.
    Code:
    final MyMidlet diz=this; // here MyMidlet is the actual Midlet class
    new Thread(new Runnable(){public void run(){
        try {
            final MyResult res=Something.DoSomething();
            Display.getDisplay(diz).callSerially(new Runnable(){public void run(){
                diz.HandleThreadResult(res,null);
            }});
        } catch (final Exception ex) {
            Display.getDisplay(diz).callSerially(new Runnable(){public void run(){
                diz.HandleThreadResult(null,ex);
            }});
        }        
    }}).start();
    
    ///////////////////////
    void HandleResult(MyResult res,Exception ex)
    {
        if(ex!=null)
            Display.getDisplay(this).setCurrent(new Alert("Error",ex.toString(),null,null);
        else
            create and display the list here
    }
    Ok, here no wrapping object was used, just passed the two possible arguments directly.
    I think there's a typo here, what did you want to write?
    I just wanted to suggest that you can freely experiment with moving parts of the code in/out from the inner (callSerially/UI) Runnable, and see what happens. For example it may be possible to create the List object completely in the background thread, and then MyResult could be the ListCustomers object, and the "create and display the list here" thing would be a simple line as Display.getDisplay(this).setCurrent(res); Or even simpler, as in the Midlet object it may be convenient to have a Display member variable somewhere, just to spare the repeated Display.getDisplay(this) part.
    Thanks again wizard_hu_ for taking the time to help me (Y)
    Once again: these fragments are not checked at all, so I just hope that they could work.
    Last edited by wizard_hu_; 2014-06-27 at 13:41.

Similar Threads

  1. Replies: 4
    Last Post: 2011-11-24, 06:05
  2. how can i make a thread?
    By buffon2009 in forum Mobile Java General
    Replies: 1
    Last Post: 2010-12-24, 07:56
  3. get the return value from thread( runnable class)
    By mramin05 in forum Mobile Java Networking & Messaging & Security
    Replies: 1
    Last Post: 2009-11-13, 17:23
  4. Replies: 2
    Last Post: 2009-03-09, 09:35
  5. How to make a carriage return?
    By chrishawaii in forum Symbian
    Replies: 4
    Last Post: 2005-06-01, 09:25

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×