java.util.concurrent.Future get() のタイムアウトを使ったコードが終了しない

このQ&Aのポイント
  • JavaのconcurrentパッケージのFuture#get()メソッドを使ってタイムアウトを設定したコードが正常に終了しない問題が発生しています。
  • concurrentパッケージのFuture#get()メソッドは、指定した時間内に結果を取得できない場合にはTimeoutExceptionをスローしますが、このコードではタイムアウトが発生した場合でも正常に終了しない問題があります。
  • 問題の原因は、コード中で指定されているTIME_BUDGETの値が0であるため、タイムアウトが発生せずに待ち続ける状態になっていることです。
回答を見る
  • ベストアンサー

java.util.concurrent.Future get() のタイムアウトを使ったコードが終了しない

こんにちは、kataoka700と言います。 以下のコードは、「Java並行処理プログラミング(ソフトバンク)」P.150のプログラムを一部変更した物です。 実行してみると終了するまで時間がかかります。しかし、mainは終わっているようです。なぜ終了しないのでしょうか。 ご存知の方はいませんか。 ■プログラム import java.util.concurrent.*; import static java.util.concurrent.TimeUnit.NANOSECONDS; public class RenderWithTimeBudget { private static final Ad DEFAULT_AD = new Ad(); private static final long TIME_BUDGET = 0; private static final ExecutorService exec = Executors.newCachedThreadPool(); Page renderPageWithAd() throws InterruptedException { long endNanos = System.nanoTime() + TIME_BUDGET; Future<Ad> f = exec.submit(new FetchAdTask()); Page page = renderPageBody(); Ad ad; try { long timeLeft = endNanos - System.nanoTime(); ad = f.get(timeLeft, NANOSECONDS); } catch (ExecutionException e) { ad = DEFAULT_AD; } catch (TimeoutException e) { ad = DEFAULT_AD; f.cancel(true); } page.setAd(ad); return page; } Page renderPageBody() { return new Page(); } static class Ad { } static class Page { public void setAd(Ad ad) { } } static class FetchAdTask implements Callable<Ad> { public Ad call() { return new Ad(); } } public static void main(String[] args) { RenderWithTimeBudget rw = new RenderWithTimeBudget(); try { rw.renderPageWithAd(); System.out.println("main() 終了"); } catch (InterruptedException e) { e.printStackTrace(); } } } ■実行結果 C:\>javac RenderWithTimeBudget.java C:\>java RenderWithTimeBudget main() 終了 C:\> ■環境 OS:WindowsXP SP3 Java:java version "1.6.0_11"

noname#91531
noname#91531
  • Java
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

ExecutorServiceをshutdownしていないからじゃないですか?

noname#91531
質問者

お礼

回答ありがとうございます。 Page renderPageWithAd() throws InterruptedException { long endNanos = System.nanoTime() + TIME_BUDGET; Future<Ad> f = exec.submit(new FetchAdTask()); try { Page page = renderPageBody(); Ad ad; try { long timeLeft = endNanos - System.nanoTime(); ad = f.get(timeLeft, NANOSECONDS); } catch (ExecutionException e) { ad = DEFAULT_AD; } catch (TimeoutException e) { ad = DEFAULT_AD; f.cancel(true); } page.setAd(ad); return page; } finally { exec.shutdown(); } } 無事終了するようになりました。 ProKaseifuさん、ありがとうございます。

関連するQ&A

  • 下記のコードを実行すると、Main.javaの

    下記のコードを実行すると、Main.javaの Command aCommand = new SimpleCommand(receiver, "action"); で、処理されない例外の型 NoSuchMethodExceptionでエラーが発生してしまうのですが、何が悪いのでしょうか?御教示お願い致します。 //ここから public abstract class Command { public abstract void execute(); } public class MyClass { public MyClass() { // } } public class SimpleCommand extends Command { public SimpleCommand(Object receiver, String action) throws NoSuchMethodException, SecurityException { _receiver = receiver; _action = action; _class = _receiver.getClass(); _method = _class.getMethod(action, null); } public void execute() { try { _method.invoke(_receiver, null); } catch (Exception e) { } } private Object _receiver; private String _action; private Class _class; private java.lang.reflect.Method _method; } public class Main { public static void main(String[] args) { MyClass receiver = new MyClass(); Command aCommand = new SimpleCommand(receiver, "action"); aCommand.execute(); } } //ここまで よろしくお願い致します。

    • ベストアンサー
    • Java
  • 他ファイルで定義された自作例外の受け方

    他ファイルで定義された自作例外の投げ方と受け方を 教えて下さい。 // ------ Class.java ---> import java.io.*; public class Class1 {  static Class2 oClass2;  public static void main (String[] args)  {   try {    oClass2 = new Class2();    System.out.println("main");    oClass2.vfFunc();   } catch (MyException e) {    System.out.println("catch MyException");   } catch (Exception e) {    System.out.println("catch Exception");   }  } } // <------ Class1.java --- // ------ Class2.java ---> import java.io.*; public class Class2 {  public Class2()  {   System.out.println("Class2コンストラクタ");  }  public void vfFunc()  {   System.out.println("Class2 vfFunc");   throw new MyException();  }  public class MyException extends Exception  {   public MyException()   {    System.out.println("MyException");   }  } } //<------ Class2.java ---

    • ベストアンサー
    • Java
  • クラス名はどうするのですか?

    package ex7; public class Sample { public final static int VALUE = 100; } package ex7; import static ex7.Sample.VALUE; public class Main { private final static int VALUE = 0; public static void main(String[] args) { System.out.println(VALUE); } } 上記のプログラムのクラス名は何をつければいいですか・・・? 同じくプログラム名は何と付ければいいですか・・・? ご多忙中恐れいります・・・。 ご回答の程宜しくお願い申し上げます。 回答者 これが、素人さんには分かりにくいんですね。 mkdir ex7 で、ex7 というディレクトリを作製して、 その中に、 Sample.java を public class Sample { public final static int VALUE = 100; } で、 Main.java を package ex7; import static ex7.Sample.VALUE; public class Main { private final static int VALUE = 0; public static void main(String[] args) { System.out.println(VALUE); } } で作製して、 ex7 の中から出て、 javac ex7/Sample.java javac ex7/Main.java でコンパイルします。 質問者 度々すいません・・・。 ファイル名は何にすればいいですか・・・? ご回答がなかなか来ません。

    • ベストアンサー
    • Java
  • java 選択肢に制限時間を設ける

    こんにちは. 現在javaでプログラムを組んでいるのですが,その中で選択肢を表示させる部分があります. この選択肢の選択に制限時間を設けたいのですが,うまくいきません. このプログラムの実現のためにどんな方法があるでしょうか? どなたかご教授お願いします. なお, public class time extends Thread { public void run() { for (int i = 3; i >= 0 ; i--) { try { sleep(1000); } catch (InterruptedException e) {} System.out.println(i); } } public static void main(String[] args) { time t = new time(); t.start(); try { System.out.println("スレッド t の終了を待機します。"); t.join(); // カウントダウンが終了するのを待つ System.out.println("スレッド t が終了しました。"); } catch (InterruptedException e) {} } } こちらのソースを参考にプログラムを書いてみましたがだめでした.

    • ベストアンサー
    • Java
  • ExecutorService.newFixedT

    はじめまして。 タイトルの通り、ExecutorService.newFixedThreadPool()で生成されたスレッド達の名前を取得しようとしています。 プログラムは以下です。 [SharedObject.java] import java.lang.Math; import java.util.Random; public class SharedObject { private int i,x; private final int[] array = new int[2500000]; private final Random r = new Random(); private long t0=0L,t1=0L; public void work() { t0 = t1 = System.nanoTime(); while((t1-t0) < 3000000000L) { synchronized (this) { x = r.nextInt(2500000); array[x] = array[x] + 1; } t1 = System.nanoTime(); } } } [Task.java] public class Task implements Runnable { private SharedObject obj; Task(SharedObject obj) { this.obj = obj; } public void run() { for(int i=0; i<3; i++) { this.obj.work(); } } } [BenchMark.java] import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.io.*; import java.util.Random; public class BenchMark { public static void main(String[] args) { ExecutorService ex = Executors.newFixedThreadPool(12); Random rnd = new Random(); int num, rnum; SharedObject obj1 = new SharedObject(); SharedObject obj2 = new SharedObject(); SharedObject obj3 = new SharedObject(); SharedObject obj4 = new SharedObject(); for(int i=0; i<500; i++) { num = rnd.nextInt(4); if(num == 0) { ex.execute(new Task(obj1)); } else if(num == 1){ ex.execute(new Task(obj2)); } else if(num == 2){ ex.execute(new Task(obj3)); } else { ex.execute(new Task(obj4)); } } ex.shutdown(); } } BenchMark.javaで12個のスレッドプールと4つのタスク(SharedObject.java)を生成しています。 各タスクから「今どのスレッドが自分にアクセスしているか」を確認するために、スレッド名を表示する機構を作りたいです。 具体的には、SharedObjectクラスの中の synchronized で囲われている部分に、その時点でロックを保持しているスレッドの getName() メソッドを呼び出すようなプログラムが書きたいと思ってるのですが、どのように書いたらいいのでしょうか? よろしくお願いします。 ※できるだけ早く回答をいただきたいので、他掲示板にもマルチポストさせていただいています。不快に思われた方にお詫び申し上げます。

    • ベストアンサー
    • Java
  • C# 例外が発生しないことの保障

    Javaと比較して書きます。 Javaで記述した場合: public class JavaClass {  public static SampleClass s = new SampleClass(); } C#で記述した場合: public class CSharpClass {  public static SampleClass s = new SampleClass(); } JavaでもC#でも、同じコードを記述しているように見えますが、Javaではnew SampleClass()コンストラクタで例外が発生しない事が分かっているのに対して、C#の場合では例外が発生しないとは言い切れません。 これは、Javaでは、例外をスローする可能性のあるメソッド宣言では、その全てについてthrows宣言をしなければいけないのに対して、C#にはこの制約が存在しないことが原因です。 これについて何が困るかといいますと、C#で、static宣言な変数や静的コンストラクタで安易にメソッド呼び出し等を行うと、キャッチできなくなってしまいます。 public class Exceptionner {  public Exceptionner()  {   throw new ApplicationException("Exceptionnerクラスの例外");  } } public class SampleClass {  public static Exceptionner e = new Exceptionner(); // ここで例外が発生するが、キャッチできない。 } public class MyEntryPoint {  public static void Main()  {   try   {    SampleClass s = new SampleClass();   }   catch (Exception e)   {    // System.ApplicationExceptionでなくSystem.TypeInitializationExceptionとなる。    // つまり、元の例外の情報は失われている    Console.WriteLine(e.GetType());   }  } } これを現在漠然と問題視していますが、何かよい解決策はありませんでしょうか。 望んでいる解決策: ・C#でもメソッドが例外を返さないという保障がソースレベルでメソッドやコンストラクタに宣言可能? ・C#では例外をちゃんとキャッチしなくてもスマートに記述することが可能? ・問題視する必要がない?(whyも含めて)

  • デッドロックに関して1

    下記のサンプルソースは、デッドロックを起こすソース なのですが、 public class Deadlock extends Thread { public static Object l1 = new Object(); public static Object l2 = new Object(); private int index; public static void main(String[] a) { Thread t1 = new ThreadA(); Thread t2 = new ThreadB(); t1.start(); t2.start(); } private static class ThreadA extends Thread { public void run() { synchronized (l1) { System.out.println("スレッド1: l1に対するロックを取得"); try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println("スレッド1: l2のロックの開放待ち"); synchronized (l2) { System.out.println("スレッド1: l1、l2に対するロックを取得"); } } } } private static class ThreadB extends Thread { 文字数オーばーのため削除 } これを参考に、Junitでデッドロックを起こすサンプルを作りたいです。 MultithreadedTestCaseと ControllableTestThreadを使い サンプルを作りたいのですが、 英語が良くわからず苦戦しております。 なにか、よいアドバイスをいただけませんでしょうか? よろしくお願いします

    • ベストアンサー
    • Java
  • java.util.Listについてです。

    以下の配列プログラムをava.util.Listを使うとどういう感じになるのでしょうか? 何卒ご回答よろしくお願い致します。 class CustomerManager { public static void main(String[] args){ CustomerManager manager = new CustomerManager(); manager.addCustomerCard( "山田一郎"); manager.addCustomerCard( "鈴木太郎"); manager.addCustomerCard( "田中次郎"); manager.printAllInfo(); } private CustomerCard[] customers = new CustomerCard[5]; private int index = 0; public void addCustomerCard(String name){ customers[index] = new CustomerCard(1 + index,name); index++; } public void printAllInfo() { System.out.print("ID =" + customers[0].id + ","); System.out.println("名前 = " + customers[0].name); System.out.print("ID =" + customers[1].id + ","); System.out.println("名前 = " + customers[1].name); System.out.print("ID =" + customers[2].id + ","); System.out.println("名前 = " + customers[2].name); } } class CustomerCard { String name; int id; public CustomerCard(int id,String name){ this.name = name; this.id = id; } public String getName(){ return this.name; } }

    • ベストアンサー
    • Java
  • java.util.Dateについて

    まずは下記ソースを参照してください。 import java.util.Date; import java.util.GregorianCalendar; import java.util.Calendar; public class Test{     public static void main( String args[] ){         GregorianCalendar cal = new GregorianCalendar(2004, 5, 31);         System.out.println("年:" + cal.get(Calendar.YEAR));         System.out.println("月:" + cal.get(Calendar.MONTH));         System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));         System.out.println(); // ただの改行         System.out.println("比較:" + new Date().compareTo(cal.getTime()));     } } 上記ソースについて質問です。 1.「年」「月」「日」を表示しておりますが、本来ならば 「年:2004」 「月:5」 「日:31」 と表示されると思っておりましたが実際は、 「年:2004」 「月:6」 「日:1」 と表示されてしまいます。 なぜでしょうか? 2.12行目にてjava.util.DateクラスのcompareToメソッドを用いて、 現在日付(2004/5/28)と7行目で指定している日付の比較をしていますが、 7行目で設定している日付を現在日付よりも前後に設定して実行させても、 「-1」しか返りません。 なぜでしょうか? 環境は、 J2SDK:1.4.2 OS:Windows XP Pro です。

    • ベストアンサー
    • Java
  • java.util.Comparatorのcompareメソッドの振る舞いについて

    はじめまして。 質問をさせていただきます。 以下のソースで、 =============================================================== import java.util.Comparator; import java.util.TreeSet; import java.util.Iterator; final class Demo { public static void main(String[] args) { TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() { public int compare(Integer i,Integer j) { int result = i%2 - j%2; if(result==0) { result = i-j; } return result; } }); for(int i=0;i<10;i++) { set.add(10-i); } Iterator<Integer> it = set.iterator(); while(it.hasNext()) { System.out.println((Integer)it.next()); } } } ================================================================ 実行結果 ================================================================ 2 4 6 8 10 1 3 5 7 9 ================================================================ 偶数が最初に昇順で出力され、奇数が後から昇順で出力されている のですが、なぜこのような実行結果になるのかがわかりません。 どうかご教授お願いします。

    • ベストアンサー
    • Java