//code taken from java concurrency in practice
package net.jcip.examples;
import java.util.concurrent.*;
public class ThreadDeadlock
{
ExecutorService exec = Executors.newSingleThreadExecutor();
public class LoadFileTask implements Callable<String> {
private final String fileName;
public LoadFileTask(String fileName) {
this.fileName = fileName;
}
public String call() throws Exception {
// Here's where we would actually read the file
return "";
}
}
public class RenderPageTask implements Callable<String>
{
public String call() throws Exception
{
Future<String> header, footer;
header = exec.submit(new LoadFileTask("header.html"));
footer = exec.submit(new LoadFileTask("footer.html"));
String page = renderBody();
// Will deadlock -- task waiting for result of subtask
return header.get() + page + footer.get();
}
}
}
该代码实际上是从Java并发中获取的,根据作者的说法,这里发生了“ThreadStarvtionDeadlock”。请帮我找到ThreadStarvationDeadlock在这里和哪里发生的情况吗?提前致谢。
最佳答案
死锁和饥饿发生在以下行:
return header.get() + page + footer.get();
如何?
如果我们在程序中添加一些额外的代码,就会发生这种情况。可能是这样的:
public void startThreadDeadlock() throws Exception
{
Future <String> wholePage = exec.submit(new RenderPageTask());
System.out.println("Content of whole page is " + wholePage.get());
}
public static void main(String[] st)throws Exception
{
ThreadDeadLock tdl = new ThreadDeadLock();
tdl.startThreadDeadLock();
}
导致死锁的步骤:
exec
,以通过Callable
实现的类RenderPageTask
呈现页面。 exec
在单独的RenderPageTask
中启动了Thread
,这是唯一的Thread
,它将执行依次提交给exec
的其他任务。 call()
的RenderPageTask
方法内部,还有两个任务提交给exec
。第一个是LoadFileTask("header.html")
,第二个是LoadFileTask("footer.html")
。但是由于如上所述通过代码exec
获得的ExecutorService Executors.newSingleThreadExecutor();
here 使用单个工作线程在不受限制的queueThread 上操作,并且该线程已经分配给RenderPageTask,因此LoadFileTask("header.html")
和LoadFileTask("footer.html")
将排队进入无界队列,等待转弯由该Thread
执行。 RenderPageTask
返回一个字符串,其中包含LoadFileTask("header.html")
输出,页面正文和LoadFileTask("footer.html")
输出的串联。在这三部分中,page
是成功获得的RenderPageTask
。但是只有通过ExecutorService
分配的单个线程执行两项任务后,才能获得其他两个部分。并且只有在call()
的RenderPageTask
方法返回后,线程才会空闲。但是,只有在返回call
和RenderPageTask
后,才会返回LoadFileTask("header.html")
的LoadFileTask("footer.html")
方法。因此,不让LoadFileTask
执行将导致 Starvation 。每个等待其他任务完成的任务都会导致 DeadLock 我希望这可以弄清楚为什么上面的代码中发生线程饥饿死锁。