我有两个Runnable
班,Reader
和Writer
。
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
来交换相同类型的数据。我怎样才能确保交换仅在Reader
和Writer
线程之间进行,而不是在两种线程之间进行交换?
答案 0 :(得分:0)
你的问题有点不清楚。由于您在这些读取器和写入器之间共享相同的交换器实例,因此没有其他线程可以参与此交换。
答案 1 :(得分: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。请注意,不会覆盖其他交换方法,但如果需要,逻辑将是相同的。