【问题标题】:How to specify the type of threads between which an exchange takes place using an exchanger?如何指定使用交换器进行交换的线程类型?
【发布时间】:2013-07-16 16:51:01
【问题描述】:

我有两个 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 线程之间进行交换,而不是在 smae 类型的两个线程之间进行?

【问题讨论】:

    标签: java multithreading java.util.concurrent


    【解决方案1】:

    你的问题有点不清楚。由于您在这些读取器和写入器之间共享相同的交换器实例,因此其他线程将无法参与此交换。

    【讨论】:

      【解决方案2】:

      如果您担心“同类”的两个线程会调用同一个 Exchanger 实例的 exchange 方法(从您带来的示例中很难猜出它是如何实现的,但您更了解您的工作组合),那么您可以拦截(通过子类化或委托,无论您更喜欢哪个)这个方法并检查线程组合是对还是错以及在每种情况下应该做什么。 这是一个子分类的例子,仅针对最简单的情况进行了测试

      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 的实际调用(如果它不破坏调用者的逻辑)。

      只需将 Exchanger 替换为您在 Reader 和 Writer ctors 调用中的类。请注意,不会覆盖另一种交换方法,但如果需要,逻辑将是相同的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-21
        • 1970-01-01
        • 2014-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-19
        • 2018-12-08
        相关资源
        最近更新 更多