2016-05-30 10 views
2

私はJavaに変換するいくつかの(Linux)Cコードを持っています。このコードには、ループループごとにOSからのTERM信号をチェックし、それ以外の場合はシグナルをブロックするメインループがあります。これは、ループ内で実行される各作業単位が完全に行われる(中間のTERMシグナルによって中断されない)ためです。Javaは、シグナルが停止するまで、作業単位を完了します

これは、Javaで実装するにはやや面白いと証明されています。私は動作するように見えるいくつかのテストコード(下)を考え出しましたが、それがいつもうまくいくかどうか、あるいは私がテストで「ラッキー」だったかどうかは分かりません。

これは私の質問です。はこの良いコードですか、時にはうまく動作するコードですか?

TL; DR:作業スレッドと、シャットダウンスレッドは、あなたはそれがあるべき期待するすべての場合に限り、シャットダウンフックが走った(完成)されるような一般的な同期方法

public class TestShutdownHook { 
    static int    a = 0;  /* should end up 0 */ 
    static volatile int b = 0;  /* exit together */ 
    static boolean   go = true; /* signaled to stop */ 

    /* 
    * this simulates a process that we want to do completely 
    * or not at all. 
    */ 
    private static void doitall() { 
     System.out.println("start"); 
     ++a;      /* simulates half the unit of work */ 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      System.out.println("exception"); /* doesn't seem to happen */ 
     } 
     System.out.println("end"); 
     --a;      /* the other half */ 
    } 

    /* 
    * there can be only one 
    */ 
    private static synchronized void syncit (String msg) { 
     if (msg.equals("exit")) go = false; 
     if (go) doitall(); 
    } 

    /* 
    * starts a thread to wait for a shutdown signal, 
    * then goes into the 'while go doit' loop 
    */ 
    public static void main(String[] args) throws InterruptedException { 
     Runtime.getRuntime().addShutdownHook(new Thread() { 
      @Override 
      public void run() { 
       int n = 0; 
       System.out.println("Shutdown coming..."); 
       syncit("exit"); /* can't happen while main is in syncit? */ 
       System.out.println("Shutdown hook! " + a); 

       /* this isn't really needed, just lets us see "goodbye" */ 
       while (b == 0) ++n; 
       System.out.println("adios..."+n); 
      }  
     }); 
     while (go) { 
      syncit("loop"); 
      // there needs to be something else in this loop 
      // otherwise, we will starve the shutdown thread. 
      // either of the two lines below seem sufficient 
      System.out.println("ok"); 
      Thread.sleep(1); 
     } 
     System.out.println("goodbye"); 
     b = 1; 
    } 
} 
+0

? JVMが正常にシャットダウンするか、^ Cでシャットダウンした場合に、doitall()が完了するはずのexitシグナルには何の欠陥もありません。私はあなたがJavaのドキュメントを読んだと思います。 –

+0

私はこれに関してかなりの数のグーグルでやっていました.JNIとsunについて多くの話題がありました。「Javaの方法は考えていません」とは言いませんが、私はこれを見つけませんでした私はいくつかの自己疑問を抱えていました。 –

答えて

1

を呼び出し、それはうまくいくはずです。 Jarrod Roberson hereによるとSIGTERMで期待どおりに動作するようです。シグナルハンドラでOS信号を明示的に捕捉する必要がない場合、私は心配する必要はないと思う。

+0

私はその質問を再読ませてくれてありがとう - 私はそれが最も有用だった[idelvallの](http://stackoverflow.com/a/33778483/2040863)答えだと思う - 彼は他のすべてのスレッドを打ちたいしかし、そこから素早く素早くクローズアップするように頼んでいました。 –

1

すべての入手可能な証拠は、あなたがShutdownHookを登録している場合はTERMまたはINT信号はJVM に配信され、他のすべてのスレッドがShutdownHookの実行まで一人で残されるとき、それが開始されることを示します()メソッドが終了します(まだ実行中のものが終了した場合)。

だから、これはを同期避ける簡単な解決策につながる:それはすべての時間を動作しないと思いますなぜ

public class AnotherTestShutdownHook { 
    static int  a   = 0;   /* should end up 0 */ 
    static boolean go   = true;  /* signaled to stop */ 
    static Thread  mainThread = Thread.currentThread(); 

    private static void trySleep (int msecs) { 
     try { Thread.sleep(msecs); } catch (InterruptedException e) {} 
    } 

    private static void tryJoin (Thread t) { 
     try { t.join(); } catch (InterruptedException e) {} 
    } 

    /* 
    * this simulates a process that we want to do completely 
    * or not at all. 
    */ 
    private static void doitall() { 
     System.out.println("start"); 
     ++a; 
     trySleep(5000); 
     System.out.println("end"); 
     --a; 
    } 

    /* 
    * starts a thread to wait for a shutdown signal, 
    * then does units of work until told to stop 
    */ 
    public static void main(String[] args) { 
     Runtime.getRuntime().addShutdownHook(new Thread() { 
      @Override 
      public void run() { 
       System.out.println("Shutdown coming..."); 
       go = false; 
       tryJoin(mainThread);  // wait for mainThread to exit 
       System.out.println("Shutdown hook! " + a); 
      }  
     }); 
     while (go) { 
      doitall(); 
     } 
     System.out.println("goodbye"); 
    } 
} 
関連する問題