2016-09-11 14 views
0

の操作に応じて、nullからnull以外、前後に変化するオブジェクトのフィールドを想定します。スレッド。NULLでない場合は値を使用し、それ以外の場合はループしてループします。

2つ目のスレッドは、null以外の値を保持するときはいつでも何らかのアクションを取る必要があります。特に、2番目のスレッドは、値がnull以外に切り替わるまで待機します。それが待たされていない場合、私はそれがその手に非nullを持っていることを確かめたい。

これは、キューの状況のようには見えません.2番目のスレッドが要素を取り去ることはないため、利用可能な場合にのみ使用します。

また、セマフォの使用には適合しません。なぜなら、再び.acquire()が許可されないからです。

代わりに、それは組み込みの待機との比較と取得を思い出させますが、これは存在しないようです。

java.util.concurrentにはこれが定義されていますが、わかりにくいデバイスがありますか?これはどうすればできますか?

Thisは類似していますが、受け入れられた回答またはここで役立つ回答はありません。

+0

アプローチには根本的な欠陥があります。レイジースレッドがフィールドの変更の間に起動することを保証できないため、すべてのイベントを捕捉できない可能性があります。 – Malt

+0

これは基本的な欠陥ではなく、意図された動作です。だからこそ、私はこう書いています。「もしそれが**起これば**、ヌル値を保持する」。そうでない場合、これは重要ではありません。 – Harald

+0

複数のスレッドが値を設定しますか? – erickson

答えて

1

フィールドを管理するには、ReentrantLockに依存する実装があります。これはダブルチェックされたロックイディオムから大きく借りていますが、値そのものを作成する代わりに、値がセットされたことを知らせるために読み取り操作が待機します。

get()メソッドにタイムアウトを許可するバージョンがオーバーロードされています。どちらのバージョンも割り込みが可能です。

import java.util.concurrent.TimeUnit; 
import java.util.concurrent.TimeoutException; 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

public class BlockingRef<V> { 

    private final Lock lock = new ReentrantLock(true); 

    private final Condition signal = lock.newCondition(); 

    private volatile V value; 

    public BlockingRef() { 
    this(null); 
    } 

    public BlockingRef(V initialValue) { 
    this.value = initialValue; 
    } 

    public final void set(V value) { 
    lock.lock(); 
    try { 
     this.value = value; 
     signal.signalAll(); 
    } finally { 
     lock.unlock(); 
    } 
    } 

    public final V get() throws InterruptedException { 
    V result = value; 
    if (result == null) { 
     lock.lockInterruptibly(); 
     try { 
     for (result = value; result == null; result = value) 
      signal.await(); 
     } finally { 
     lock.unlock(); 
     } 
    } 
    return result; 
    } 

    public final V get(long time, TimeUnit unit) 
    throws TimeoutException, InterruptedException 
    { 
    V result = value; 
    if (result == null) { 
     long start = System.nanoTime(); 
     if (!lock.tryLock(time, unit)) throw new TimeoutException(); 
     try { 
     time = unit.toNanos(time); 
     for (result = value; result == null; result = value) { 
      long wait = time - (System.nanoTime() - start); 
      if (wait <= 0) throw new TimeoutException(); 
      signal.await(wait, TimeUnit.NANOSECONDS); 
     } 
     } finally { 
     lock.unlock(); 
     } 
    } 
    return result; 
    } 

    @Override 
    public String toString() { 
    return String.valueOf(value); 
    } 

} 
関連する問題