2016-11-13 15 views
0

基本的には、メソッドを呼び出した後にスレッドを一時停止してから、もう一方のスレッドに移ります。私はループすることはできません、私の方法は一度だけ実行することができます。 これの背後にある考え方は、メソッドがメッセージを表示するゲームで使用され、ユーザーがキーを押すたびに次のメッセージが表示されます。ゲームがユーザーからの入力を受け入れるので、私はリストを通過することはできません。 Thread.pause()Thread.resume()が表示されますが、これらはどちらも機能しません。廃止予定です。 (動作していない)私の現在のコード:メソッドが呼び出された後のスレッドの一時停止

private Thread thread; 
private Thread managerThread; 
private final Object lock = new Object(); 

private boolean shouldThreadRun = true; 
private boolean storyRunning = true; 

public Storyline() { 
    setUpThread(); 
} 

private void setUpThread() { 
    managerThread = new Thread(() -> { 
     while(storyRunning) { 
      synchronized (lock) { 
       if(!shouldThreadRun) { 
        try { 
         lock.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
       System.out.println("Looping"); 
      } 
     } 
    }); 
    thread = new Thread(() -> { 
     synchronized (lock) { 
      pauseThread(); 
      System.out.print("A"); 
      pauseThread(); 
      System.out.print("B"); 
     } 
    }); 
    managerThread.start(); 
    thread.start(); 
} 

public void pauseThread() { 
    shouldThreadRun = false; 
} 
public void resumeThread() { 
    shouldThreadRun = true; 
} 
+0

あなたは 'resumeThread()'をどこからでも呼び出すことができます。また、 'shouldThreadRun'は、異なるスレッドによって変更されて読み込まれる場合、' volatile'と宣言されるべきです。 –

+0

https://docs.oracle.com/javase/tutorial/essential/concurrency/join.html –

+0

「B」が印刷されるかどうかを確認するためにテストしていたので、印刷しないでください。しかし、それは印刷されます –

答えて

0

は私の編集を見て、それはあなたが達成しようとしていたものに任意の似ているかどうかを確認します。私はユーザ入力をシミュレートするためにスキャナを使用しています。キーボードのEnterキーを押して試してみてください。ところで、私はこれが単なる運動であり、実際の生活状況ではないことを願っています。実際に必要な場合を除き、このような低レベルのマルチスレッド管理は、実際の製品では避けるようにしてください。この場合、適切なデータ構造を使用する必要があります。実際のアプリケーションでは、ボタンはコールバックにリンクされ、ボタンを押すとすぐに必要なコードを実行するonClick()メソッドがいくつか設定されます。

同時実行に関する何のため

、私は強くあなたがこれらのチュートリアルを見てみることをお勧め:Oracle-Concurrency

がPS:私は完全に割り込みを無視してることがわかり、悪い習慣である、これらの例外は、右を処理する必要がありますway:私は、コードをできるだけシンプルに保つことによって、望ましい結果を達成しようとしていました。また、他の誰かが指摘したように、ループの中で待機を呼び出すだけで偽の起床を処理する必要があります。

private Thread thread; 
private Thread managerThread; 
private final Object lock = new Object(); 

Scanner in; 

public Storyline() { 
    setUpThread(); 
} 

private void setUpThread() { 
    managerThread = new Thread(() -> { 
     while(true) { 
      in = new Scanner(System.in); 
      in.nextLine(); 
      resumeThread(); 
     } 
    }); 
    thread = new Thread(() -> { 
     synchronized (lock) { 
      while(true){ 
       System.out.print("A"); 
       try { 
        lock.wait(); 
       } catch (InterruptedException e) {} 
       System.out.print("B"); 
       try { 
        lock.wait(); 
       } catch (InterruptedException e) {} 
      } 
     } 
    }); 
    managerThread.start(); 
    thread.start(); 
} 


public void resumeThread() { 
    synchronized(lock){ 
     lock.notify(); 
    } 
} 
+0

私は誰がこれを落としたのかわからない、それはトリックをした、ありがとう! –

+0

私はうれしいです – c0rtexx

0

はObject.wait、as described in the documentationの最初のルールは、それ待ちのための基礎となる条件に依存してループ内で呼び出さなければならないということです。

だから、あなたの待ち時間は次のように見ている必要があります

synchronized (lock) { 
    while (!shouldThreadRun) { 
     lock.wait(); 
    } 
} 

割り込みは、事故によって起こるものではありません。スレッドは、別のスレッドが何をしているのかを明示的に要求して正常に終了した場合にのみ中断されます。

したがって、割り込みが発生した場合は、正しいアクション・コースはではなく、であり、スタック・トレースを無視して印刷します。あなたはきれいに退出する必要があります。ときに中断

try { 
    while (storyRunning) { 
     synchronized (lock) { 
      while (!shouldThreadRun) { 
       lock.wait(); 
      } 
      System.out.println("Looping"); 
     } 
    } 
} catch (InterruptedException e) { 
    System.out.println("Exiting, because someone asked me to stop."); 
    e.printStackTrace(); 
} 

この方法では、あなたのwhileループは自動的に終了します:のtry/catchでループしながら、

これを行う最も簡単な方法は、単にあなたの全体を囲むことです。

最後に、待機中のスレッドが同期しているものと同じオブジェクト上の別のスレッドがObject.notifyまたはObject.notifyAllを呼び出さない限り、Object.waitは無意味です。オブジェクトが通知を受け取らない限り、waitメソッドは返されません。

public void pauseThread() { 
    synchronized (lock) { 
     shouldThreadRun = false; 
     // Tell waiting thread that shouldThreadRun may have changed. 
     lock.notify(); 
    } 
} 

public void resumeThread() { 
    synchronized (lock) { 
     shouldThreadRun = true; 
     // Tell waiting thread that shouldThreadRun may have changed. 
     lock.notify(); 
    } 
} 

同期がメソッド内にあることに注意してください。スレッドを常にlockに同期させておくと、同じオブジェクトに対して同期ロックを取得しようとしているため、マネージャスレッドはまったく実行できません。(ただし、逆は真ではありません。lockすべての時間に同期を維持することができますマネージャスレッド、待機()メソッドは、一時的に他のスレッドが続行できるように、同期ロックを解除しますので。)全ての場合

同期化ブロックがshouldThreadRunにアクセスするコードは同期化されたブロックの内側にあるため、同期化によってすでにマルチスレッド整合性が保証されているため、shouldThreadRunを揮発性にする必要はありません。

関連する問題