• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Thread Pool and Scheduler

 
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Questions regarding Threading. The structure of my code is...

The UI thread calls a Routine R0 which *uses a background thread*  to call two Routines R1 and R2 which each need to retrieve information from the internet. R1 and R2 are called in succession. R1 must complete before R2 is called. This sequence is done in a loop, with each iteration selecting the next item from an ArrayList to operate on.

*Note* I believe that R0 does not need to use a backgroud thread as it is R1 and R2 which go to the internet. But it works in simple testing so I'll leave it as is for now.

R1 and R2 each extend Thread, so each begins with a public void run() {...}. Also each needs to store a result on the UI thread so each uses a runOnUiThread(new Runnable(...)) at the end of its processing.

All of the code works perfectly (with a bit of cheating, a finite loop after calls to R1 and R2 waiting for the result) when tested in a simple environment where there is no possibility of a conflict. When installed in the App it works perfectly for the first iteration then the App "hangs" - it does not finish the next  
iteration, it literally just sits there; no processing is going on as the LogCat has paused; and the program does respond to other menu selections correctly - so it has not "crashed";

I have not been this deep into Threads so I have been reading and getting confused by several blogs posts etc on the topic of Threads, so I have some quesstions...

Do I need to use a thread pool?
Will I need to use a Scheduler?
Does anyone have a favorite, good basic introduction to this topic?  Especially one with an introductory level example?

Hopefully, next time I will have some code to show

Thank you,
Mick
 
Marshal
Posts: 28263
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Mick, welcome to the Ranch!

There's no point in me trying to explain anything about concurrency here, as there's far too much to cover and 99% of it is irrelevant to your situation. So let's just talk about your problem description.

You say there are two tasks, R1 and R2. And R2 can't run until R1 is finished. So it seems to me that putting them in different threads is a bad idea, since then you have to build a structure which forces that to happen. Wouldn't it be simpler to have one thread which runs R1 and then R2?

As for your code which isn't working right, I'm sure that a bit of debugging should help you to see what is or isn't happening.
 
Saloon Keeper
Posts: 27886
198
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'd concur with Paul, but since you mentioned a UI thread, I'd like to caution you against running any part of the application on the UI thread unless absolutely necessary.

If you are using a common GUI system such as Swing, the UI is Model/View/Controller based. MVC is predicated on the idea that changes to the Model will be automatically updated (via the Controller) to the View (visible display) and that changes made to the View (data controls) will likewise be reflected back (again, via the Controller) into the Model.

In other words, rather than messing around with the View/Controller logic, it's generally better if your tasks simply update the Model, then post an "update view" request to the GUI itself.

If you do that, then your logic becomes simpler, threading issues are reduced and you don't risk making the GUI stutter and sputter. Or render into places it shouldn't.
 
Mick Dawdy
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Paul,
Each of tasks R1 and R2 accesses the internet, which is a relatively long running process. But each starts the access then returns immediately. I must delay the start of R2 until after that long running R1 process finishes. I believe that is why R1 and R2 may need to be in different threads, and need to be run by a scheduler.

As I mentioned the code works perfectly when the components are run independently of each other. But in the final App R1 and R2 are in a loop processing data from an ArrayList. Each of these uses a single-statement runOnUiThread to store the result. If I put a finite delay loop after each, waiting for the new value to appear in a global String result field, it all works. But such a delay loop is problematic in Android. I need to find a better technique than this...

Although I have more than 50 years experience in technical computer programming I am new to concurrent processing in Android; and as you imply,  it is a daunting topic. This is why I am looking for a good starting point, especially something with an example. There is a lot "out there", I'll sort through it somehow.
Thank you,
Mick
 
Mick Dawdy
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Tim,
I have seen references to Swing but I have do not know what it is, or any similar packages, although it does sound interesting. I am using straight Java within Android Studio. I have also looked at RxJava but it appears to be another daunting topic. So I am looking really for understanding or perhaps concurrence with my problem description, and a starting point to a solution, especially something with an example

Mick
 
Tim Holloway
Saloon Keeper
Posts: 27886
198
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh. An ANDROID app.

That's different. And much uglier. Android and JavaScript have an inside-out UI threading model that makes everything much more cumbersome.

I'm bouncing this thread over to the Android forum.

Android does still adhere to the MVC paradigm, but yes, long-running operations do need to spin off worker threads lest they jam up the GUI. The problem is, they've tried about 6 different and generally incompatible generations of multi-threading and I'm not sure that they're done even yet. The latest recommendation uses the "new" standard Java threading services, though. so it may be a bit more stable.
 
Mick Dawdy
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you. Sorry for not mentioning Android in my original post
 
Paul Clapham
Marshal
Posts: 28263
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mick Dawdy wrote:Hi Paul,
Each of tasks R1 and R2 accesses the internet, which is a relatively long running process. But each starts the access then returns immediately. I must delay the start of R2 until after that long running R1 process finishes. I believe that is why R1 and R2 may need to be in different threads, and need to be run by a scheduler.




Here the r1() method starts, runs for a long time, then terminates. At that point it's safe to run the r2() method. Which runs for a long time and then terminates. That's what your requirements say. To me that says R1 and R2 should be in the same thread. I don't see why a scheduler is necessary either.

But each starts the access then returns immediately


Is that an external requirement imposed on you? Because it makes your system much more complex and less reliable. If you don't have to do that then I suggest don't do it.
 
Ranch Hand
Posts: 607
11
Android Python Open BSD VI Editor Slackware
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mick Dawdy wrote:

Does anyone have a favorite, good basic introduction to this topic?  Especially one with an introductory level example?

Hopefully, next time I will have some code to show

Thank you,
Mick



Sure we need to distinguish two cases. 1) You are interested in the theory of the concurrency 2) you want  to utilize what  currently the industry uses.

1) too broad topic and too many tools to use, since roughly 2011 is not common anymore to see in Android Thread and Pools at a low level, but with specific tools google engineers offered dedicated abstrations and unfortunately some of them are deprecated.
2) you may want to use coroutines, they simplify in a great way how to manage structured concurrency, and are defined( improperly) as light weight threads. Basically they use a system of caching and deferring calls simplifying the readability of your code and giving you full control for your use case.
I suggest you to look for the two options `launch` and `async` both of them can be used for your use case.

If really you want to go deep with Threads, I suggest you the dedicated chapter on Head first Java as an introduction, and then a book called java concurrency in practice, the second one is the bible of the concurrency in java. I repeat good to know, but in 2023 nobody is going to land on a job without knowing more industry modern methods, RXJava, and coroutines with Flow at least.
 
Mick Dawdy
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you for this good information
 
Giovanni Montano
Ranch Hand
Posts: 607
11
Android Python Open BSD VI Editor Slackware
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mick Dawdy wrote:Thank you for this good information



Here a working example, this is the way you would pass a modern code review in the industry:
please notice the comments //first //second etc, this is the way the log will appear using async instead of launch:



Notice result is returned when both the functions are BOTH returned, the same you can do if you really want to execute a first call and wait for the result, just use `await` and assign to a variable the flow will stop, here you are making both the call in parallel (faster), and when both of them are executed a result is returned.

If you want the use case of running first function1 that has a delay of 1 sec, and then function 2 that has a delay 10 times slower(should run before in theory) you can use withContext



as this link explains:

function 2 executes faster than function 1 since function 2 has less delay then function 1. Since withContext is a suspend call, that is it won’t go to the next line until it finished. Since withContext is a suspend call and does not block the main thread, we can do other tasks while the IO thread is busy in executing function1 and function 2.



a suspend call  is a function that could be started, paused, and resumed.
usually you use the  keyword suspend:



Once you understand these 3 concepts suspend, launch and await, you an safely run threads without so called race concurrency problems, this is the magic of the "structured concurrency" you isolate/encapsulate the thread and can use entry and exit points you want, and manage as a police man with the traffic all the other threads as you like, also in this way you can propagate eventual errors and manage in an easier way,

There is another layer of complexity that is managing parent and child threads, basically you can define that a child fails independently from the other children or that terminates even the parent, this allow you great architectural choices.
 
reply
    Bookmark Topic Watch Topic
  • New Topic