2013-07-16 76 views
0

我有兩個Runnable類,ReaderWriter如何指定使用交換器進行交換的線程類型?

import java.io.IOException; 
import java.io.RandomAccessFile; 
import java.nio.ByteBuffer; 
import java.util.concurrent.Exchanger; 

public class Reader implements Runnable { 
    private static final int THRESHHOLD = 1000; 
    private final int START, STOP; 
    private Exchanger<ByteBuffer> exch; 
    private RandomAccessFile file; 
    private ByteBuffer buffer; 

    public Reader(Exchanger<ByteBuffer> ex, RandomAccessFile f, int start, int stop) { 
     START = start; 
     STOP = stop; 
     exch = ex; 
     file = f; 
     buffer = ByteBuffer.allocate(THRESHHOLD); 
     buffer.mark(); 
    } 

    @Override 
    public void run() { 
     for(int i = START; i < STOP; i++) 
      try { 
       buffer.put((byte)file.read()); 
      } catch(IOException e) { 
       e.printStackTrace(); 
      } 
     try { 
      exch.exchange(buffer); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 



import java.io.IOException; 
import java.io.RandomAccessFile; 
import java.nio.ByteBuffer; 
import java.util.concurrent.Exchanger; 
import java.util.concurrent.locks.ReentrantLock; 

public class Writer implements Runnable { 
    private static final int THRESHHOLD = 1000; 
    private final int START, STOP; 
    private ReentrantLock lock; 
    private Exchanger<ByteBuffer> exch; 
    private RandomAccessFile file; 
    private ByteBuffer buffer; 

    public Writer(Exchanger<ByteBuffer> e, ReentrantLock l, RandomAccessFile f, int start, int stop) { 
     lock = l; 
     START = start; 
     STOP = stop; 
     exch = e; 
     file = f; 
    } 

    @Override 
    public void run() { 
     try { 
      buffer = exch.exchange(ByteBuffer.allocate(THRESHHOLD)); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
     lock.lock(); 
     for(int i = START; i < STOP; i++) 
      try { 
       file.write(buffer.get()); 
      } catch(IOException e) { 
       e.printStackTrace(); 
      } 
     lock.unlock(); 
    } 

} 

這兩個線程都使用Exchanger來交換相同類型的數據。我如何確保交換隻發生在ReaderWriter線程之間,而不是兩個線程之間的交換?

回答

0

你的問題不太清楚。由於您在這些閱讀器和書寫器之間共享相同的交換器實例,因此其他線程無法參與此交換。

0

如果您擔心兩個「相同類型」的線程可能會調用同一個Exchanger實例的交換方法(很難從您帶來的示例中猜出它是如何可能的,但您更瞭解自己的工作組合),那麼你可以攔截(通過子類或通過委派,無論你喜歡哪個)這個方法,並檢查線程組合是對還是錯,以及在每種情況下應該做什麼。 這裏是子類的實例,只是一個簡單的情況下

public class ThreadStrictExchanger<V> extends Exchanger<V> { 
    private Thread waitingThread; 

    @Override 
    public V exchange(V x) throws InterruptedException { 
     Thread currentThread = Thread.currentThread(); 
     if (waitingThread == null){ 
      waitingThread = currentThread; 
     } else { 
      checkThreads(waitingThread, currentThread); 
      waitingThread = null; 
     } 
     return super.exchange(x); 
    } 

    private void checkThreads(Thread waitingThread, Thread currentThread) { 
     //TODO add here your logic/change 
    } 
} 

你可以按類型或名稱的兩個線程測試對比(使用Thread.setName()/的getName())。如果checkThreads方法中兩個線程的組合是錯誤的 - 要麼拋出異常,要麼返回false以指示實際的Exchanger.exchange調用應該被跳過(如果它不打斷調用者的邏輯)。

只需在Reader和Writer ctors的調用中將Exchanger替換爲您的類即可。請注意,另一種交換方法未被覆蓋,但如果需要,邏輯將相同。