[关闭]
@linux1s1s 2019-02-15T21:20:29.000000Z 字数 1553 阅读 2285

线程饥饿死锁

JavaThread 2015-11


Executor

我们知道,Executor框架可以将任务的提交和任务的执行解耦出来,它是如何做到解耦的,下面会举例子详细说明。说回上面的话题,上面的话题多少有点言过其实,虽然Executor框架为制定和修改执行策略都提供了相当大的灵活性,但是,也不是所有的任务都是适用相同的执行策略,比如以下几种:

下面将给出其中 依赖性任务的列子

Demo

  1. public class ThreadDeadLock {
  2. ExecutorService executor = Executors.newSingleThreadExecutor();
  3. public class RenderPageTask implements Callable<String> {
  4. @Override
  5. public String call() throws Exception {
  6. Future<String> header, footer;
  7. header = executor.submit(new LoadFileTask("header_task"));
  8. Log.i("Channel", "executor.submit(new LoadFileTask(\"header_task\"))");
  9. footer = executor.submit(new LoadFileTask("footer_task"));
  10. Log.i("Channel", "executor.submit(new LoadFileTask(\"footer_task\"))");
  11. String result = header.get() + " " + footer.get();
  12. Log.i("Channel", "result: " + result);
  13. return result;
  14. }
  15. }
  16. public void render() {
  17. executor.submit(new RenderPageTask());
  18. Log.i("Channel", "executor.submit(new RenderPageTask())");
  19. }
  20. public class LoadFileTask implements Callable<String> {
  21. private String loadName;
  22. LoadFileTask(String loadName) {
  23. this.loadName = loadName;
  24. }
  25. @Override
  26. public String call() throws Exception {
  27. return loadName;
  28. }
  29. }
  30. }

然后测试一下

  1. private void loadFileRender() {
  2. final ThreadDeadLock deadLock = new ThreadDeadLock();
  3. deadLock.render();
  4. }

为什么Log.i("Channel", "result: " + result);没有打印出来,我们先来简单分析一下即可。

RenderPageTask 任务首先在单线程中执行,然后在RenderPageTask这个任务又提交了LoadFileTask任务到单线程中去,因为RenderPageTask依赖LoadFileTask,而单线程中LoadFileTask只能在RenderPageTask任务结束以后才能有机会得到执行,所以出现了死锁。

所以依赖性任务很容易出现隐性耦合,我们将上面代码L2 简单修改一下,其他不用修改

  1. ExecutorService executor = Executors.newCachedThreadPool();

仅仅修改执行的策略即可,其他不用修改,是不是体会到任务的提交和任务的执行完全解耦了啊

修改为多线程情况下,死锁得到解除。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注