Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to quickly complete thread scheduling and task management in Android Bolts

2025-01-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

Android Bolts in how to quickly complete thread scheduling and task management, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, hope you can gain something.

Using Bolts, a complete operation can be divided into multiple subtasks, which can be split, combined and replaced freely. Each task can be run in a specified thread as a part of the whole task chain. At the same time, it can not only obtain the results of the task from the uplink task, but also publish the results of the current task to the downlink task, regardless of the interaction between threads.

Implementation of Bolts-Android Bolts under Android implementation of Bolts-ObjC Bolts under OC implementation of Bolts-Swift Bolts under Swift

Preface

A simple requirement about thread scheduling is that the child thread downloads the image from the network and returns the downloaded image, updates the image to UI in the main thread, returns the current UI status json, saves the json data to the local file in the child thread, and pops up the prompt in the main thread after completion, which involves 4 thread switches, and the latter task needs the return value after the completion of the previous task as a parameter.

Using Thread + Handler implementation, thread scheduling is very inflexible, code readability is poor, ugly, poor scalability, error handling is very troublesome.

String url = "http://www.baidu.com"; Handler handler = new Handler (Looper.getMainLooper ()); new Thread (()-> {/ / download Bitmap bitmap = downloadBitmap (url); handler.post (()-> {/ / update UI String json = updateUI (bitmap); new Thread (()-> {/ / write UI status saveUIState (json) to storage) / / after saving successfully, prompt handler.post (()-> toastMsg ("save finish.");}) .start ();});}) .start ()

Using RxJava implementation, thread scheduling is very flexible, chain calls, clear code, good scalability, a unified exception handling mechanism, but Rx is a very powerful library, if only used for thread scheduling, Rx seems a bit too heavy.

Observable.just (URL) / / download .map (this::downloadBitmap) .subscribeOn (Schedulers.newThread ()) / update UI .subscrieOn (AndroidSchedulers.mainThread ()) .map (this::updateUI) / / Store UI status.subscrieOn (Schedulers.io ()) .map (this::saveUIState) / / display prompt .subscrieOn (AndroidSchedulers.mainThread ()) .subscribe (rst-> toastMsg ("save to" + rst) / / handle error Throwable::printStackTrace)

Using bolts to achieve, flexible thread scheduling, chain calls, clear code, good scalability, with a unified exception handling mechanism, although not as rich as Rx operators, but the class library is very small, only 38 KB.

Task .forResult (URL) / / download .onsuccess (task-> downloadBitmap (task.getResult ()), Task.BACKGROUND_EXECUTOR) / / Update UI .onSuccess (task-> updateUI (task.getResult ()), Task.UI_THREAD_EXECUTOR) / / Store UI status.onsuccess (task-> saveUIState (task.getResult () Task.BACKGROUND_EXECUTOR) / / prompt .onsuccess (task-> toastMsg ("save to" + task.getResult ()), Task.UI_THREAD_EXECUT / / handle error .continueWith (task-> {if (task.isFaulted ()) {task.getError (). PrintStackTrace ()) Return false;} return true;})

Thread scheduler

There are four types of execution threads that distribute tasks to the specified thread for execution, namely

Backgroud-backstage thread pool that allows tasks to be executed concurrently.

Scheduled-single thread pool, with only one thread, is mainly used to perform delay operations.

Immediate-Instant thread, if the thread call stack is less than 15, it executes on the current thread, otherwise the proxy is given to background.

UiThread-designed for Android, sent to the main thread using Handler for execution.

Backgroud

It is mainly used to perform multiple tasks concurrently in the background.

Public static final ExecutorService BACKGROUND_EXECUTOR = BoltsExecutors.background ()

Under the Android platform, create a thread pool based on the number of CPU cores, and in other cases, create a cache thread pool.

Background =! isAndroidRuntime ()? Java.util.concurrent.Executors.newCachedThreadPool (): AndroidExecutors.newCachedThreadPool ()

Scheduled

It is mainly used to do delay operations between tasks, and does not actually perform tasks.

Scheduled = Executors.newSingleThreadScheduledExecutor ()

Immediate

Mainly used to simplify those methods that do not specify the running thread, default in the current thread to execute the task, use ThreadLocal to save the depth of each thread call stack, if the depth is not more than 15, then execute in the current thread, otherwise the agent to backgroud execution.

Private static final Executor IMMEDIATE_EXECUTOR = BoltsExecutors.immediate (); / / key method @ Override public void execute (Runnable command) {int depth = incrementDepth (); try {if (depth whenAnyResult (Collection > tasks) public static Task > whenAny (Collection > tasks)

Use the whenAll method to execute multiple tasks, and return the result when all the tasks have been executed

Public static Task whenAll (Collection > tasks) public static Task > whenAllResult (final Collection > tasks)

Using the call method, perform a task while creating a Task

Public static Task call (final Callable callable, Executor executor, final CancellationToken ct)

Link subtask

Using the continueWith method, link a subtask, and if the forward task has been completed, execute the current task immediately, otherwise join the queue and wait.

Public Task continueWith (final Continuation continuation, final Executor executor, final CancellationToken ct)

Using the continueWithTask method, link another task chain after the current task, in order to satisfy the scenario where some tasks are grouped together and separated, and as a common task, he accepts another completely separate task chain, appended to the currently executed task.

Public Task continueWithTask (final Continuation continuation, final Executor executor, final CancellationToken ct)

Using the continueWhile method to link subtasks differs from continueWith in that it has an predicate expression that appends subtasks only when the expression is established, so that you can do an intercept operation before executing the task, but also in order not to break the overall style of chain calls.

Public Task continueWhile (final Callable predicate, final Continuation continuation, final Executor executor, final CancellationToken ct)

Use onSuccess and onSuccessTask to link a single task chain, which is different from the continueWith method. If the forward task fails, the later task will fail directly and will no longer be executed, but there is no correlation between the subtasks of the continueWith. Even if the forward task fails, the latter task will be executed.

Public Task onSuccess (final Continuation continuation, Executor executor, final CancellationToken ct)

Cancel the task

CancellationTokenSource cancellationTokenSource = new CancellationTokenSource (); CancellationToken token = cancellationTokenSource.getToken (); Task.call ((Callable) ()-> null, Task.BACKGROUND_EXECUTOR, token); / / cancel task cancellationTokenSource.cancel ()

Exception handling

With regard to exception handling, under the whole mechanism, each task as an independent unit, exceptions will be caught uniformly, so it is not necessary to handle the methods in the task separately.

If you use a continueWith linked task, the exception information of the current task will be saved in the current Task for processing in the downstream task, and the downstream task can execute the task without handling the exception. Then the exception will stop here and will not be passed downwards, that is to say, only the downstream task will know the result of the current task, whether successful or abnormal.

Of course, if there is a connection between tasks, because the exception of the uplink task is most likely to cause the exception of the current task, then the information of the exception of the current task will be passed down again, but the exception of the uplink task ends here.

If you use a method such as onSuccess, if the uplink task is abnormal, the downlink task will not be executed at all, but will pass the exception directly down until it is disposed of.

Separation and combination of tasks

We can subdivide a complete operation into multiple tasks, each of which follows the principle of a single responsibility and is as simple as possible, so that new tasks can be interspersed between tasks, or some tasks can be separated and combined together.

Expansibility

We can add a new operation between the two subdivided tasks without affecting the uplink and downlink tasks, such as saving the Bitmap locally before we update the UI in the requirements at the beginning of the article.

Task .forResult (URL) / / download .onsuccess (task-> downloadBitmap (task.getResult ()), Task.BACKGROUND_EXECUTOR) / / save locally .onsuccess (task-> saveBitmapToFile (task.getResult ()), Task.BACKGROUND_EXECUTOR) / / update UI .onsuccess (task-> updateUI (task.getResult ()), Task.UI_THREAD_EXECUTOR).

Reusability

For some common operations, can be separated into new tasks, when you need to do similar operations, you can reuse this part of the function, such as download pictures and update UI, save the status and pop-up prompts out of the two functions, as a public task.

/ / download picture-> update UI public Continuation downloadImageAndUpdateUI () {return task-> Task.call (()-> downloadBitmap (task.getResult ()), Task.BACKGROUND_EXECUTOR) .continueWith (taskWithBitmap-> updateUI (taskWithBitmap.getResult ()), Task.UI_THREAD_EXECUTOR) } / / Save status-> prompt message public Continuation saveStateAndToast () {return task-> Task.call (()-> saveUIState (task.getResult ()), Task.BACKGROUND_EXECUTOR) .continueWith (taskWithPath-> toastMsg ("save to" + taskWithPath.getResult ();}

Use separate tasks

Task .forResult (URL) .continueWithTask (downloadImageAndUpdateUI ()) .continueWithTask (saveStateAndToast ())...

In Task, a continuations is an appended task list after the current task. When the current task succeeds, exceptions, or cancels, the subsequent tasks in the list will be executed.

Typically, we use chained calls to build a task chain, and the result is a task chain with no branches.

When adding a task: each time a Continuation is added, a Task is generated, which is added to the continuations list of the uplink task, waiting for execution, while returning the current Task, so that subsequent tasks can be linked to the current task.

When executing a task: after the execution of the current task, there may be three results, all of which will be saved to the current Task, and then check the subsequent tasks in the continuations list, and the current Task will be passed as a parameter to the subsequent linked tasks to let the later tasks know the results of the uplink task.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report