当前位置:   article > 正文

华为Harmony鸿蒙开发笔记十一:线程管理_鸿蒙线程管理demo

鸿蒙线程管理demo

鸿蒙的线程是有TaskDispatcher类来分发的,TaskDispatcher有四种GlobalTaskDispatcher、ParallelTaskDispatcher、SerialTaskDispatcher、SpecTaskDispatcher。

创建对象:

  1. private String parallelName = "parallelTaskDispatcher";
  2. private String serialName = "serialTaskDispatcher";
  3. private TaskDispatcher globalTaskDispatcher;//全局并发任务分发器
  4. private TaskDispatcher parallelTaskDispatcher;//并发任务分发器
  5. private TaskDispatcher serialTaskDispatcher;//串行任务分发器
  6. private TaskDispatcher uiTaskDispatcher;//专有任务分发器
  7. @Override
  8. public void onStart(Intent intent) {
  9. super.onStart(intent);
  10. super.setUIContent(ResourceTable.Layout_ability_main);
  11. globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
  12. parallelTaskDispatcher = createParallelTaskDispatcher(parallelName, TaskPriority.DEFAULT);
  13. serialTaskDispatcher = createSerialTaskDispatcher(serialName, TaskPriority.DEFAULT);
  14. uiTaskDispatcher = getUITaskDispatcher();
  15. }

测试同步任务代码:

  1. private void testSyncDispatch() {
  2. globalTaskDispatcher.syncDispatch(new Runnable() {
  3. @Override
  4. public void run() {
  5. try {
  6. Thread.sleep(5000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. HiLog.info(label, "sync task1 run");
  11. }
  12. });
  13. HiLog.info(label, "after sync task1");
  14. parallelTaskDispatcher.syncDispatch(new Runnable() {
  15. @Override
  16. public void run() {
  17. try {
  18. Thread.sleep(5000);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. HiLog.info(label, "sync task2 run");
  23. }
  24. });
  25. HiLog.info(label, "after sync task2");
  26. serialTaskDispatcher.syncDispatch(new Runnable() {
  27. @Override
  28. public void run() {
  29. try {
  30. Thread.sleep(5000);
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34. HiLog.info(label, "sync task3 run");
  35. }
  36. });
  37. HiLog.info(label, "after sync task3");
  38. uiTaskDispatcher.syncDispatch(new Runnable() {
  39. @Override
  40. public void run() {
  41. try {
  42. Thread.sleep(5000);
  43. } catch (InterruptedException e) {
  44. e.printStackTrace();
  45. }
  46. HiLog.info(label, "sync task4 run");
  47. }
  48. });
  49. HiLog.info(label, "after sync task4");
  50. }

输出日志:

  1. 01-24 09:14:31.488 4741-27498/com.example.dispatcherdemo I 00201/MY_TAG: sync task1 run
  2. 01-24 09:14:31.489 4741-4741/com.example.dispatcherdemo I 00201/MY_TAG: after sync task1
  3. 01-24 09:14:36.490 4741-27783/com.example.dispatcherdemo I 00201/MY_TAG: sync task2 run
  4. 01-24 09:14:36.491 4741-4741/com.example.dispatcherdemo I 00201/MY_TAG: after sync task2
  5. 01-24 09:14:41.492 4741-28065/com.example.dispatcherdemo I 00201/MY_TAG: sync task3 run
  6. 01-24 09:14:41.492 4741-4741/com.example.dispatcherdemo I 00201/MY_TAG: after sync task3

syncDispatch是派发同步任务,可以看出无论哪种分发器,只要使用syncDispatch来派发任务,都是同步执行的,有点协程的味道。最后一个uiTaskDispatcher没有执行是因为发生了死锁,官网说以下情况使用syncDispatch会导致死锁:

如果对syncDispatch使用不当, 将会导致死锁。如下情形可能导致死锁发生:

  • 在专有线程上,利用该专有任务分发器进行syncDispatch。
  • 在被某个串行任务分发器(dispatcher_a)派发的任务中,再次利用同一个串行任务分发器(dispatcher_a)对象派发任务。
  • 在被某个串行任务分发器(dispatcher_a)派发的任务中,经过数次派发任务,最终又利用该(dispatcher_a)串行任务分发器派发任务。例如:dispatcher_a派发的任务使用dispatcher_b进行任务的派发,在dispatcher_b派发的任务中又利用dispatcher_a进行派发任务。
  • 串行任务分发器(dispatcher_a)派发的任务中利用串行任务分发器(dispatcher_b)进行同步派发任务,同时dispatcher_b派发的任务中利用串行任务分发器(dispatcher_a)进行同步派发任务。在特定的线程执行顺序下将导致死锁

测试异步任务代码:

  1. private void testAsyncDispatch() {
  2. globalTaskDispatcher.asyncDispatch(new Runnable() {
  3. @Override
  4. public void run() {
  5. try {
  6. Thread.sleep(5000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. HiLog.info(label, "async task1 run");
  11. }
  12. });
  13. HiLog.info(label, "after async task1");
  14. parallelTaskDispatcher.asyncDispatch(new Runnable() {
  15. @Override
  16. public void run() {
  17. try {
  18. Thread.sleep(5000);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. HiLog.info(label, "sync task2 run");
  23. }
  24. });
  25. HiLog.info(label, "after sync task2");
  26. serialTaskDispatcher.asyncDispatch(new Runnable() {
  27. @Override
  28. public void run() {
  29. try {
  30. Thread.sleep(5000);
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34. HiLog.info(label, "sync task3 run");
  35. }
  36. });
  37. HiLog.info(label, "after sync task3");
  38. uiTaskDispatcher.asyncDispatch(new Runnable() {
  39. @Override
  40. public void run() {
  41. try {
  42. Thread.sleep(5000);
  43. } catch (InterruptedException e) {
  44. e.printStackTrace();
  45. }
  46. HiLog.info(label, "sync task4 run");
  47. }
  48. });
  49. HiLog.info(label, "after sync task4");
  50. }

日志输出:

  1. 01-24 09:24:37.406 9317-9317/com.example.dispatcherdemo I 00201/MY_TAG: after async task1
  2. 01-24 09:24:37.407 9317-9317/com.example.dispatcherdemo I 00201/MY_TAG: after sync task2
  3. 01-24 09:24:37.407 9317-9317/com.example.dispatcherdemo I 00201/MY_TAG: after sync task3
  4. 01-24 09:24:37.408 9317-9317/com.example.dispatcherdemo I 00201/MY_TAG: after sync task4
  5. 01-24 09:24:42.407 9317-30393/com.example.dispatcherdemo I 00201/MY_TAG: async task1 run
  6. 01-24 09:24:42.407 9317-30394/com.example.dispatcherdemo I 00201/MY_TAG: sync task2 run
  7. 01-24 09:24:42.409 9317-9317/com.example.dispatcherdemo I 00201/MY_TAG: sync task4 run
  8. 01-24 09:24:42.409 9317-30395/com.example.dispatcherdemo I 00201/MY_TAG: sync task3 run

无论哪种分发器,只要使用了asyncDispatch分发任务,都是异步执行,既然这样,为什么还要给分发器分类呢。

先测试一下Paralle和Serial分发异步任务

  1. private void testSerialDispatch() {
  2. serialTaskDispatcher.asyncDispatch(new Runnable() {
  3. @Override
  4. public void run() {
  5. try {
  6. Thread.sleep(5000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. HiLog.info(label, "serialTaskDispatcher sync task1 run");
  11. }
  12. });
  13. HiLog.info(label, "serialTaskDispatcher after sync task1");
  14. serialTaskDispatcher.asyncDispatch(new Runnable() {
  15. @Override
  16. public void run() {
  17. try {
  18. Thread.sleep(1000);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. HiLog.info(label, "serialTaskDispatcher sync task2 run");
  23. }
  24. });
  25. HiLog.info(label, "serialTaskDispatcher after sync task2");
  26. }
  27. private void testParalleDispatch() {
  28. parallelTaskDispatcher.asyncDispatch(new Runnable() {
  29. @Override
  30. public void run() {
  31. try {
  32. Thread.sleep(5000);
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. HiLog.info(label, "parallelTaskDispatcher sync task1 run");
  37. }
  38. });
  39. HiLog.info(label, "parallelTaskDispatcher after sync task1");
  40. parallelTaskDispatcher.asyncDispatch(new Runnable() {
  41. @Override
  42. public void run() {
  43. try {
  44. Thread.sleep(1000);
  45. } catch (InterruptedException e) {
  46. e.printStackTrace();
  47. }
  48. HiLog.info(label, "parallelTaskDispatcher sync task2 run");
  49. }
  50. });
  51. HiLog.info(label, "parallelTaskDispatcher after sync task2");
  52. }

日志:

  1. 01-24 09:36:52.844 15707-15707/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher after sync task1
  2. 01-24 09:36:52.845 15707-15707/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher after sync task2
  3. 01-24 09:36:53.845 15707-8432/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher sync task2 run
  4. 01-24 09:36:57.845 15707-8431/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher sync task1 run
  5. 01-24 09:37:00.949 15707-15707/com.example.dispatcherdemo I 00201/MY_TAG: serialTaskDispatcher after sync task1
  6. 01-24 09:37:00.950 15707-15707/com.example.dispatcherdemo I 00201/MY_TAG: serialTaskDispatcher after sync task2
  7. 01-24 09:37:05.950 15707-8894/com.example.dispatcherdemo I 00201/MY_TAG: serialTaskDispatcher sync task1 run
  8. 01-24 09:37:06.951 15707-9210/com.example.dispatcherdemo I 00201/MY_TAG: serialTaskDispatcher sync task2 run

原来,使用使用syncDispatch和asyncDispatch分发任务,同步异步是针对于主线程的,而ParallelTaskDispatcher、SerialTaskDispatcher的区别是自己派发出去的任务是串行还是并行。

常规操作延时执行:

  1. private void testDelayDispatch() {
  2. globalTaskDispatcher.delayDispatch(new Runnable() {
  3. @Override
  4. public void run() {
  5. HiLog.info(label, "delayDispatch task1 run");
  6. }
  7. }, 50000);
  8. HiLog.info(label, "after delayDispatch task1");
  9. }

鸿蒙还可以将线程分组,将几个线程放在一个group中,并且可以添加这一组线程执行完的回调:

  1. private void testGroupDispatch() {
  2. // 创建任务组。
  3. Group group = parallelTaskDispatcher.createDispatchGroup();
  4. // 将任务1加入任务组,返回一个用于取消任务的接口。
  5. parallelTaskDispatcher.asyncGroupDispatch(group, new Runnable(){
  6. @Override
  7. public void run() {
  8. try {
  9. Thread.sleep(1000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. HiLog.info(label, "download task1 is running");
  14. }
  15. });
  16. // 将与任务1相关联的任务2加入任务组。
  17. parallelTaskDispatcher.asyncGroupDispatch(group, new Runnable(){
  18. @Override
  19. public void run() {
  20. try {
  21. Thread.sleep(1000);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. HiLog.info(label, "download task2 is running");
  26. }
  27. });
  28. // 在任务组中的所有任务执行完成后执行指定任务。
  29. parallelTaskDispatcher.groupDispatchNotify(group, new Runnable(){
  30. @Override
  31. public void run() {
  32. HiLog.info(label, "the close task is running after all tasks in the group are completed");
  33. }
  34. });
  35. }

日志:

  1. 01-24 09:49:25.346 4247-8522/com.example.dispatcherdemo I 00201/MY_TAG: download task1 is running
  2. 01-24 09:49:25.348 4247-8523/com.example.dispatcherdemo I 00201/MY_TAG: download task2 is running
  3. 01-24 09:49:25.349 4247-8587/com.example.dispatcherdemo I 00201/MY_TAG: the close task is running after all tasks in the group are completed

对于分组任务还可以设置屏障任务:可以使用asyncDispatchBarrier和syncDispatchBarrier来派发异步或同步的屏障线程,这种线程必须是在Group线程执行完成后,才执行的

  1. private void testBarrierDispatch() {
  2. // 创建任务组。
  3. Group group = parallelTaskDispatcher.createDispatchGroup();
  4. // 将任务加入任务组,返回一个用于取消任务的接口。
  5. parallelTaskDispatcher.asyncGroupDispatch(group, new Runnable(){
  6. @Override
  7. public void run() {
  8. HiLog.info(label, "parallelTaskDispatcher task1 is running"); // 1
  9. }
  10. });
  11. parallelTaskDispatcher.asyncGroupDispatch(group, new Runnable(){
  12. @Override
  13. public void run() {
  14. HiLog.info(label, "parallelTaskDispatcher task2 is running"); // 2
  15. }
  16. });
  17. parallelTaskDispatcher.syncDispatchBarrier(new Runnable() {
  18. @Override
  19. public void run() {
  20. try {
  21. Thread.sleep(1000);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. HiLog.info(label, "parallelTaskDispatcher barrier is running"); // 3
  26. }
  27. });
  28. HiLog.info(label, "parallelTaskDispatcher after syncDispatchBarrier"); // 4
  29. TaskDispatcher parallelTaskDispatcher2 = createParallelTaskDispatcher("dispatcherName", TaskPriority.DEFAULT);
  30. // 创建任务组。
  31. Group group2 = parallelTaskDispatcher2.createDispatchGroup();
  32. // 将任务加入任务组,返回一个用于取消任务的接口。
  33. parallelTaskDispatcher2.asyncGroupDispatch(group2, new Runnable(){
  34. @Override
  35. public void run() {
  36. HiLog.info(label, "parallelTaskDispatcher2 task1 is running"); // 1
  37. }
  38. });
  39. parallelTaskDispatcher2.asyncGroupDispatch(group2, new Runnable(){
  40. @Override
  41. public void run() {
  42. HiLog.info(label, "parallelTaskDispatcher2 task2 is running"); // 2
  43. }
  44. });
  45. parallelTaskDispatcher2.asyncDispatchBarrier(new Runnable() {
  46. @Override
  47. public void run() {
  48. try {
  49. Thread.sleep(1000);
  50. } catch (InterruptedException e) {
  51. e.printStackTrace();
  52. }
  53. HiLog.info(label, "parallelTaskDispatcher2 barrier is running"); // 3
  54. }
  55. });
  56. HiLog.info(label, "parallelTaskDispatcher2 after asyncDispatchBarrier"); // 4
  57. }
  58. 日志:
  59. 01-24 10:08:15.493 30657-9662/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher task1 is running
  60. 01-24 10:08:15.493 30657-9663/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher task2 is running
  61. 01-24 10:08:16.494 30657-9664/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher barrier is running
  62. 01-24 10:08:16.495 30657-30657/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher after syncDispatchBarrier
  63. 01-24 10:08:16.496 30657-9727/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher2 task1 is running
  64. 01-24 10:08:16.496 30657-30657/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher2 after asyncDispatchBarrier
  65. 01-24 10:08:16.496 30657-9728/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher2 task2 is running
  66. 01-24 10:08:17.497 30657-9729/com.example.dispatcherdemo I 00201/MY_TAG: parallelTaskDispatcher2 barrier is running

取消任务:Revocable是取消一个异步任务的接口。异步任务包括通过 asyncDispatch、delayDispatch、asyncGroupDispatch 派发的任务。如果任务已经在执行中或执行完成,则会返回取消失败。

  1. private void testRevocableDispatch() {
  2. Revocable revocable = parallelTaskDispatcher.delayDispatch(new Runnable() {
  3. @Override
  4. public void run() {
  5. HiLog.info(label, "delay dispatch");
  6. }
  7. }, 1000);
  8. boolean revoked = revocable.revoke();
  9. HiLog.info(label, "%{public}b", revoked);
  10. }
  11. 日志:
  12. 01-24 09:53:45.649 7590-7590/com.example.dispatcherdemo I 00201/MY_TAG: true

执行多次任务:对指定任务执行多次,使用applyDispatch配合CountDownLatch使用,可以让线程重复执行指定次数:

  1. final int total = 10;
  2. final CountDownLatch latch = new CountDownLatch(total);
  3. final ArrayList<Long> indexList = new ArrayList<>(total);
  4. private void testApplyDispatch() {
  5. // 执行任务 total 次
  6. globalTaskDispatcher.applyDispatch((index) -> {
  7. indexList.add(index);
  8. HiLog.info(label, "applyDispatch index="+index);
  9. latch.countDown();
  10. }, total);
  11. // 设置任务超时
  12. try {
  13. latch.await();
  14. } catch (InterruptedException exception) {
  15. HiLog.info(label, "latch exception");
  16. }
  17. HiLog.info(label, "list size matches, %{public}b", (total == indexList.size()));
  18. }
  19. 日志:
  20. 01-24 10:16:31.939 29071-7870/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=0
  21. 01-24 10:16:31.940 29071-7871/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=1
  22. 01-24 10:16:31.940 29071-7873/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=3
  23. 01-24 10:16:31.941 29071-7874/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=4
  24. 01-24 10:16:31.941 29071-7875/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=5
  25. 01-24 10:16:31.941 29071-7872/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=2
  26. 01-24 10:16:31.942 29071-7877/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=7
  27. 01-24 10:16:31.943 29071-7878/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=8
  28. 01-24 10:16:31.943 29071-7879/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=9
  29. 01-24 10:16:31.943 29071-7876/com.example.dispatcherdemo I 00201/MY_TAG: applyDispatch index=6
  30. 01-24 10:16:31.943 29071-29071/com.example.dispatcherdemo I 00201/MY_TAG: list size matches, true

Demo:https://download.csdn.net/download/y280903468/14926982

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/283242
推荐阅读
相关标签
  

闽ICP备14008679号