現在、これを行う正しい方法を見つけるのに問題があります。スレッドを必要とするメソッドによってデッドロックが発生する
私は、固定スレッドプールが64のExecutorServiceを持っています。一種のブック(一度に1つ)をダウンロードするよう依頼しています。私が必要とする本をダウンロードするには:書籍情報をダウンロードし、ページ情報をダウンロードして、書籍の一部をダウンロードします。私が本をダウンロードするように要求するとき、私はすべてのページ情報を得て、同じ方法で私はその本の小さな部分をダウンロードする。問題は、書籍のこれらの小さな部分をダウンロードすることも非同期的に(別のスレッドが必要です)実行されていますが、64スレッドすべてがページダウンロードスレッドによって占有されていました。私は別のExecutorServiceを追加するか、スレッドプールを256のようなより大きな数に持ち上げることに思いつきました。しかし、それはちょうどいい感じではありません。他のオプションはありますか?デッドロック - - アウト部による
- ページ情報
ページの一部:
- ダウンロード帳情報
ダウンロードページ:手順と問題の場所の
概要のスレッド。
@Override public Book getBook(int bookId) { Book book = books.get(bookId); if (book == null) { HttpURLConnection conn = factory.getBook(bookId); String s = read(conn); book = interpret.readBook(s); books.put(book.getId(), book); } return book; } @Override public Page getPage(int bookId, int pageNum) { String s = read(factory.getPage(bookId, pageNum)); List<Integer> eIds = interpret.readExercises(s); List<Exercise> exercises = new ArrayList<>(eIds.size()); CountDownLatch latch = new CountDownLatch(eIds.size()); System.out.println("D: Requesting to dl page " + bookId + '>' + pageNum); for (int eId : eIds) { System.out.println("eId" + eId); service.submit(() -> { try { // The code here does not execute to the lack of free threads System.out.println("D: Requesting to dl exer " + eId); String sE = read(factory.getExercise(bookId, eId)); Exercise exercise = interpret.readExercise(sE); exercises.add(exercise); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } }); } try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } return new Page(pageNum, exercises); } @Override public WholeBook getWholeBook(int bookId) { Book book = getBook(bookId); List<Page> pages = new ArrayList<>(book.getPages().size()); CountDownLatch latch = new CountDownLatch(book.getPages().size()); System.out.println("D: Requesting to dl book " + bookId); for (int pageNum : book.getPages()) { service.submit(() -> { try { Page page = getPage(bookId, pageNum); System.out.println("Got page: " + page); pages.add(page); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } }); } try { System.out.println("Waiting for book " + bookId); latch.await(); } catch (InterruptedException e) { e.printStackTrace(); return null; // Better to return null rather than corrupted data } return new WholeBook(book, pages); }
出力の最後には、次のとおりです。 D: Requesting to dl page 10753>67 eId235082 eId235092
それは(技術的に実行されているが、何もしていない)を停止した後
私が(デバッガを使用して)、スレッドを中断すると、スタックトレースは#getPageを指し、正確にはlatch.await()
になります。
コードが必要です。実際にネットワークにアクセスする必要のない、自己完結型のものをお選びください。それは、なぜこれが「デッドロック」するのか、または飢えているのかわかりません。タスクを完了したら、新しいタスクのためにスレッドを使用できるようにする必要があります。 – markspace
@Kayamanはコード – Mibac
を追加しました。@markspaceしかし、タスクは実際に完了するために別のスレッドが必要です – Mibac