1.饥饿死锁介绍
在线程池中,如果任务依赖于其他任务,那么可能产生死锁。在单线程Executor中,如果一个任务将另一个任务提交到同一个Executor,并且等待这个被提交任务的结果,那么通常会发生死锁。第二个任务停留在工作队列中,并等待第一个任务完成,而第一个任务又无法完成,因为它在等待第二个任务的完成。在更大的线程池中,如果所有正在执行任务的线程都由于等待其他仍处于工作队列中的任务而阻塞,那么就会发生同样的问题。这种现象被称为线程饥饿死锁,只要线程池中的任务需要无限期的等待一些必须由池中其他任务才能提供的资源或条件,例如某任务等待另一个任务的返回值,那么除非线程池足够大,否则会发生线程饥饿死锁。
2.下面是饥饿死锁的实例
场景:RenderPageTaskExecutor提交了两个任务来获取网页的页眉和页脚,绘制页面,等待获取页眉和页脚任务的结果,然后将页眉,页面主题和页脚组合起来形成最终界面。如果使用单线程的Executor,那么ThreadDeadLock会发生死锁。(如果多线程,在线程值不够大的情况下,也会发生死锁)
public class ThreadDeadLock {
ExecutorService exec = Executors.newSingleThreadExecutor();
public class LoadFileTask implements Callable<String>{
private final String fileName;
public LoadFileTask(String fileName) {
this.fileName = fileName;
}
@Override
public String call() throws Exception {
//这里我们应该读取文件
return "";
}
public class RenderPageTask implements Callable<String>{
@Override
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();
//这里会发生死锁
return header.get()+page+footer.get();
}
private String renderBody() {
//这里我们读取界面的信息
return "";
}
}
}
}