2012-09-25 5 views
5

私はマルチスレッドに慣れていません。マルチスレッドについては読んでいますが、この複雑なマルチスレッドコードを書いて次のことを行うと思います。スレッド1からスレッド2によって通知されるまで待つ方法

私のカウンタークラスは以下の通りです。

class Counter { 
    private int c = 0; 

    public void increment() { 
    System.out.println("increment value: "+c); 
     c++; 
    } 

    public void decrement() { 
     c--; 
     System.out.println("decrement value: "+c); 
    } 

    public int value() { 
     return c; 
    } 

} 

このカウンタオブジェクトは2つのスレッド間で共有されます。 スレッドが開始されたら、私は次のことを行う必要があります。 Thread1がCounterオブジェクトのカウントを1だけインクリメントするまでThread2を待機させます。 これが完了すると、Thread1はthread2に通知し、Thread1はthread2の待機を開始して値を1減らします。 次にthread2が値を開始し、 1を返し、thread1に再度通知し、thread2はthread1の待機を開始します。このプロセスを数回繰り返します。

これをどうすれば実現できますか?事前に多くの感謝。

私は以下を行っています。

public class ConcurrencyExample { 

    private static Counter counter; 
    private static DecrementCount t1; 
    private static IncrementCount t2; 

    public static void main(String[] args) { 
    Counter counter = new Counter(); 
    Thread t1 = new Thread(new IncrementCount(counter)); 
    t1.start(); 

    Thread t2 = new Thread(new DecrementCount(counter)); 
    t2.start(); 

    } 

} 


public class DecrementCount implements Runnable { 

    private static Counter counter; 

    public DecrementCount(Counter counter) { 
    this.counter = counter; 
    } 

    @Override 
    public void run() { 
    for (int i = 0; i < 1000; i++) { 
     counter.decrement();  
     System.out.println("decreamented"); 
    } 
    } 

} 


public class IncrementCount implements Runnable { 

    private static Counter counter; 

    public IncrementCount(Counter counter) { 
    this.counter = counter; 
    } 

    @Override 
    public void run() { 
    for (int i = 0; i < 1000; i++) { 
     counter.increment(); 
     System.out.println("Incremented"); 
    } 

    } 

} 
+2

CountDownLatchを参照してください。http://docs.oracle.com/javase/1.5.0/docs/apc/java/util/concurrent/CountDownLatch.html – davidmontoyago

+1

IncrementCountは、 'increment()'を呼び出す必要があります。 –

+1

これを行う最も簡単な方法は、1つのスレッドを使用することです。私は、複数のスレッドを使用するほうが複雑で遅くなるのではなく、高速になる例を考えることをお勧めします。 –

答えて

3

チェックアウトSemaphore。スレッドごとに1つずつ、2つ、つまりincSemaphoredecSemaphoreが必要です。 DecrementCountで行います

for (int i = 0; i < 1000; i++) { 
    decSemaphore.acquire(); 
    counter.decrement();  
    System.out.println("decreamented"); 
    incSemaphore.release(); 
} 

は対称的にIncrementCountを実装します。 incSemaphoreの初期値は、decSemaphoreの場合、10である必要があります。

あなたのCounterでも同期が必要です(​​キーワードとAtomicIntegerを参照)。

+0

+1。 – dcernahoschi

0

ブール値フラグ付きのConditionを使用してください。

final Lock lock = new ReentrantLock(); 
final Condition incremented= lock.newCondition(); 
final Condition decremented= lock.newCondition(); 

以下の説明に、あなたのカウンターを変更し

我々は1がインクリメントされ、1つが減算される二つの条件を使用していました。 booleanフラグに基づいて、1つの条件で待機する必要があるかどうかをチェックします。

class Counter { 
private int c = 0; 
boolean increment = false; 

final Lock lock = new ReentrantLock(); 
final Condition incremented = lock.newCondition(); 
final Condition decremented = lock.newCondition(); 

public void increment() throws InterruptedException { 
    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     while(increment) 
      decremented.await(); 
     increment = true;   
     c++; 
     System.out.println("increment value: " + c); 
     incremented.signal(); 
    } finally { 
     lock.unlock(); 
    } 

} 

public void decrement() throws InterruptedException { 

    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     while (!increment) 
      incremented.await(); 
     c--; 
     System.out.println("decrement value: " + c); 
     increment = false; 
     decremented.signal(); 
    } finally { 
     lock.unlock(); 
    } 
} 

public int value() { 
    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     return c; 
    } finally { 
     lock.unlock(); 
    } 
} 

} 
+0

何人かが-1を説明できますか? –

+0

最初は答えは役に立たなかった。今はまし。 – Gray

+0

@Gray提供されたコードもあります。分かりやすくするために、 –

0

-まずあなたincrement()decrement()レースを回避するために​​キーワードを使用しなければならない条件は、このブライアンのルールを参照してください

When we write a variable which has just been read by another thread, or reading a variable which is just lately written by another thread, must be using Synchronization. And those atomic statements/Methods accessing the fields' data must be also synchronized.

-その持ちJVM Thread Scheduler制御どのスレッドが実行状態に入るか、それがどれくらい長くそこにとどまるか、そして仕事が終わった後にどこに行くのかということです。スレッドが最初に実行されるの一つCannot be sure .....

- -

をあなたはまた、java.util.concurrentからSingleThreadExecutorを使用することができますが、これは、第二の上に移動する前に一つのタスクを完了します。

+0

あなたはブライアンのルールを誤って引用していますが、とにかく正しくありません。揮発性物質の使用もまた解決策である。 –

+0

@MartinSerranoまず、何らかの声明について誤って書かれた証拠がない場合は、間違っていないことを指摘してください。第二に、疑問があればBruce EikleによるJava Bookの思考の第4版を参照してください...今は私が書いたことは正しいです、そして私はあなたがまだ十分に揮発性で遊んでいないと思います。フィールドをvolatileにすると、そのフィールドにアクセスするステートメントがSingle atomic statement ..... –

関連する問題