代码之家  ›  专栏  ›  技术社区  ›  Lydon Ch

为什么会陷入僵局

  •  4
  • Lydon Ch  · 技术社区  · 14 年前

    清单8.1中的代码“实践中的Java并发”

    为什么代码死锁?是因为 rpt.call 在里面 main() 与执行器中的线程基本相同吗?

    即使我用10个线程 exec = Executors.newFixedThreadPool(10); 还是僵局?

    public class ThreadDeadlock {
      ExecutorService exec = Executors.newSingleThreadExecutor();
    
      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();
        }
      }
    
       public static void main(String [] args ) throws Exception {
    
            ThreadDeadlock td = new ThreadDeadlock();
            ThreadDeadlock.RenderPageTask rpt = td.new RenderPageTask();
            rpt.call();
        }
    }
    
    1 回复  |  直到 8 年前
        1
  •  9
  •   axtavt    14 年前

    您的代码不会死锁-下面是:

    public class ThreadDeadlock { 
        ...     
        public static void main(String [] args ) throws Exception { 
            ThreadDeadlock td = new ThreadDeadlock(); 
            ThreadDeadlock.RenderPageTask rpt = td.new RenderPageTask(); 
    
            Future<String> f = td.exec.submit(rpt);
    
            System.out.println(f.get());
            td.exec.shutdown();
        } 
    }
    

    当第一个任务等待以下任务的结果时,如果您向单线程执行器提交多个并发任务,就会发生这种情况。它不会死锁 Executors.newFixedThreadPool(2) 因为 LoadFileTask S是独立的,可以在使用另一个线程时共享一个线程 RenderPageTask .

    此示例的要点是,如果将相互依赖的任务提交给 ExecutorService 您应该确保线程池的容量足以以所需的并行级别执行它们。