0

I am new to threading and i went through many post in stack overflow and find many solution for my problem but i am not sure which one is best for which condition.

First thing first, my problem is that i want to update one JSON file when all threads are done with the bitmap generation at a specific path so that i can get that all those image and update JSON file. So in simple word my i want to run some code when all thread are done with it execution and major requirement is that i don't want my main to be blocked because of this.

What i have found out

  • thread. join
  • excutorServive
  • android-priority-jobQueue (link)
  • Mutex in threadpool ( also let me know if any other is there)

I am confused which one is the best way to tackle my problem. if any android expert out there can summarise that for following the two scenerio what is the best available in android.

  • wait till when all thread completes
  • don't wait and get informed when all completes
RATHI
  • 5,129
  • 8
  • 39
  • 48

3 Answers3

0

You can have counter for your threads, after each thread is complete check how many have already completed, if not all completed, increment the number of completed threads and the last thread to complete will then run the piece of code.

KgaboL
  • 130
  • 5
  • can you be little more descriptive in usage. i don't know how many thread will be running. it is a variable too. as i don;t know how many bitmap generation will be there. second thing i want it to completely independent module from my application. How to come to know that a thread is completed? for that i need to have a while loop in one thread (correct me if i am wrong) – RATHI Jun 21 '16 at 07:34
  • @RATHI extending KgaboL's answer, the same moment you start a thread, you can increase a counter (set in a static class, if you want). When a thread ends, decrease that counter, and check if it equals zero. When it's zero, it would mean all the threads are gone. You'd still need to take into account what happens when a set of threads are no longer necessary (lazy loading some images that are no longer onscreen, for instance), like making sure the final job won't execute unless you create threads again, or something like that. – Sergi Juanola Jun 21 '16 at 07:39
  • @Korcholis thanks for the answer, what can be used for this approach, i am thinking to go with a thread pool executor. actually i confused in this, don't want to again jump to another approach later in future. – RATHI Jun 21 '16 at 07:49
  • @RATHI look for implementations out there. I'd personally choose to create a class that handles thread generation and management in a singleton way –but who knows, I'm a fan of singletons! Anyway, in Android (virtually anywhere, even web), you still need to think if it's necessary to finish the threads even if the user closes the app, in which case an intent service like GPuschka suggests might be _the_ option – Sergi Juanola Jun 21 '16 at 08:08
0

You can do it like this.

In your thread:

private Runnable runnableThread= new Runnable() {
    @Override
    public void run() {
        try {
            if (lastThreadDone){
                handler.sendEmptyMessage("SUCCESS");
            }
        }
        catch (Exception ex) {
            throws ex;
        }
    }
};

lastThreadDone is boolean which will become true if the process is done, this is base on how you implement it.

then in you handler:

@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        try {
            switch (msg.what) {
                case "SUCCESS": {
                    // your code here 
                    break;
                }
                case "FAIL":
                    break;
                default:
                    break;
            }
        }
        catch (Exception ex) {
            throw ex;
        }
        super.handleMessage(msg);
    }
};
Rashid
  • 1,700
  • 1
  • 23
  • 56
  • That is the question i think that how will you come to know that last thread has completed? it is not always that last thread that was queued will be the last one executing. isn't it? let suppose that i have started 6 thread and at the end of all these six i should get this message. so what i can think of is that i can have a mutex on count and when every thread is done with execution i can decrease that count and when the last thread runs at that time i can send this message to the handler. but this require lot of concurrency which i need to handle. – RATHI Jun 21 '16 at 07:44
  • i think this is a well known problem and there should be some good option to easily handle this thing in android. correct me if i am excepting too much from android. :P – RATHI Jun 21 '16 at 07:46
  • most like there is a limitation for threads right now. i recommend to try Asynctask which is more suitable solution for your problem, refer here http://stackoverflow.com/a/24228697/5870896 – Rashid Jun 21 '16 at 07:51
  • I think Async thread should use when you have some 2 or 3 task i mean when you are not looking for much parallelism and by default asynctask run serially. so i don't think that that will be a good option in my case. – RATHI Jun 21 '16 at 07:54
  • normally on main thread that image rendition generation takes 2 to 3 sec each. that there can be as much 20 image generation at a time – RATHI Jun 21 '16 at 07:56
  • what i would like to suggest is to use my code above, then on handleMessage, increment an integer. and check if the size is already equal to what you expected. that way you know that all the thread calls is finish – Rashid Jun 21 '16 at 07:58
0

I would use a completion service and then poll until all tasks are finished. When they are done, the json file gets updated. The problem is that you need to do this async or you risk to block the ui. Therefore I would encapsulate the work with the completion service inside an intent service. If you need to update the ui you then can post local broadcasts from the intent service.

Furthermore for you cases

  • wait till when all thread completes

    • only do this when you are already on a background thread like intent service or async task
  • don't wait and get informed when all completes

    • implies the case above. Do the work async and notify the ui or some listening component with broadcasts, content observers, handlers or the 'onPostExecute' if you are using async task.
Community
  • 1
  • 1
GPuschka
  • 522
  • 3
  • 9
  • Thank for the answer, this is looking some promising but from that thread, "Basically you use a CompletionService if you want to execute multiple tasks in parallel and then work with them in their completion order. So, if I execute 5 jobs, the CompletionService will give me the first one that that finishes" , i don't need each thread order wise result, i want want to get informed that they are finished – RATHI Jun 21 '16 at 08:13
  • will the thread pool inside the intent service also a good option? – RATHI Jun 21 '16 at 08:17
  • Sure, whatever fits the purpose. As for the completion service, it does return the first task that finished, but you can pull as many times as you submitted a task. When the pull counter matches the submit counter you know that every task was executed. When using the intent service remember that the intent service is destroyed after the execution so don't rely on any state. – GPuschka Jun 21 '16 at 08:25
  • didn't get you're last line. – RATHI Jun 21 '16 at 08:37
  • One more thing, in case of service isn't the priority of the spawn thread by that service will be less and won't it take much more time to complete all the thread as compared to main thread thread pool? – RATHI Jun 21 '16 at 08:40
  • Basically do everything inside the 'onStartCommand' method of the intent service. If you set some king of instance variables, they should be gone between the service invocations. As for the second question above, honestly I don't know what the priority is. I just know that it gets the job done. Doing stuff on the main thread might execute faster but it freezes the ui and might lead to an [ANR](https://developer.android.com/training/articles/perf-anr.html) if its not fast enough resulting in the job not being done at all. – GPuschka Jun 21 '16 at 08:47