专栏首页算法之名让两个线程安全的交换对象 顶

让两个线程安全的交换对象 顶

JDK中有一个Exchanger交换类可以让两个线程的对象安全互换,注意这里是互换,而不是谁传给谁。这是一个传递字符数组的互换。

public class ProducerTask implements Runnable {
    private final Exchanger<char[]> exchanger;
    private char[] buffer = null;
    private char index = 0;
    private final Random random;
    public ProducerTask(Exchanger<char[]> exchanger,char[] buffer,long seed) {
        this.exchanger = exchanger;
        this.buffer = buffer;
        this.random = new Random(seed);
    }
    @Override
    public void run() {
        try {
//            while (true) {
            //向缓冲区填充字符
            for (int i = 0; i < buffer.length; i++) {
                buffer[i] = nextChar();
                System.out.println(Thread.currentThread().getName() + ": " + buffer[i] + " -> ");
            }
            //交换缓冲区
            System.out.println(Thread.currentThread().getName() + ": BEFORE exchange");
            //此处会将使用同一个交换机的两个线程的字符数组互换,如果一个字节数组为空,次数为堵塞等待
            buffer = exchanger.exchange(buffer);
            System.out.println(Thread.currentThread().getName() + ": AFTER exchange");
            for (int i = 0;i < buffer.length;i++) {
                System.out.println(Thread.currentThread().getName() + ": -> " + buffer[i]);
            }
//            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private char nextChar() throws InterruptedException {
        char c = (char)('A' + index % 26);
        index++;
//        Thread.sleep(random.nextInt(1000));
        return c;
    }
}
public class SteadTask implements Runnable {
    private final Exchanger<char[]> exchanger;
    private char[] buffer = null;
    private final Random random;
    private char index = 0;

    public SteadTask(Exchanger<char[]> exchanger, char[] buffer,long seed) {
        this.exchanger = exchanger;
        this.buffer = buffer;
        this.random = new Random(seed);
    }

    @Override
    public void run() {
        try {
//            while (true) {
            //向缓冲区填充字符
            for (int i = 0; i < buffer.length; i++) {
                buffer[i] = nextChar();
                System.out.println(Thread.currentThread().getName() + ": " + buffer[i] + " -> ");
            }
            //交换缓冲区
            System.out.println(Thread.currentThread().getName() + ": BEFORE exchange");
            //此处会将使用同一个交换机的两个线程的字符数组互换
            buffer = exchanger.exchange(buffer);
            System.out.println(Thread.currentThread().getName() + ": AFTER exchange");
            for (int i = 0;i < buffer.length;i++) {
                System.out.println(Thread.currentThread().getName() + ": -> " + buffer[i]);
            }
//            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private char nextChar() throws InterruptedException {
        char c = (char)('Z' - index % 26);
        index++;
//        Thread.sleep(random.nextInt(1000));
        return c;
    }
}
public class Main {
    public static void main(String[] args) {
        Exchanger<char[]> exchanger = new Exchanger<>();
        char[] buffer1 = new char[10];
        char[] buffer2 = new char[10];
        new Thread(new ProducerTask(exchanger,buffer1,314159)).start();
//        new Thread(new ConsumerTask(exchanger,buffer2,265358)).start();
        new Thread(new SteadTask(exchanger,buffer2,265358)).start();
    }
}

运行结果:

Thread-1: Z -> Thread-0: A -> Thread-1: Y -> Thread-0: B -> Thread-1: X -> Thread-0: C -> Thread-1: W -> Thread-0: D -> Thread-1: V -> Thread-0: E -> Thread-1: U -> Thread-0: F -> Thread-1: T -> Thread-0: G -> Thread-0: H -> Thread-0: I -> Thread-0: J -> Thread-1: S -> Thread-0: BEFORE exchange Thread-1: R -> Thread-1: Q -> Thread-1: BEFORE exchange Thread-1: AFTER exchange Thread-1: -> A Thread-1: -> B Thread-1: -> C Thread-1: -> D Thread-1: -> E Thread-0: AFTER exchange Thread-1: -> F Thread-1: -> G Thread-1: -> H Thread-1: -> I Thread-1: -> J Thread-0: -> Z Thread-0: -> Y Thread-0: -> X Thread-0: -> W Thread-0: -> V Thread-0: -> U Thread-0: -> T Thread-0: -> S Thread-0: -> R Thread-0: -> Q

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 浅谈parallelStream 顶

    parallelStream是什么,它是一个集合的并发处理流.其作用是把一个集合中的数据分片,进行一个多线程的处理,增快运行速度.

    算法之名
  • 如何自己实现一个BlockingQueue 顶

    Thread-0 Requests [ Request No.0 ] Thread-1 handles [ Request No.0 ] Thread-0 ...

    算法之名
  • 线程,JVM锁整理

    首先wait()和notify(),notifyAll()方法一定是一般对象方法,他们并不属于线程对象方法,一定是跟synchronized(监视器锁)结伴出现...

    算法之名
  • 某团面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    最近网上出现一个美团面试题:“一个线程OOM后,其他线程还能运行吗?”。我看网上出现了很多不靠谱的答案。这道题其实很有难度,涉及的知识点有jvm内存分配、作用域...

    芋道源码
  • 某团面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    最近网上出现一个美团面试题:“一个线程OOM后,其他线程还能运行吗?”。我看网上出现了很多不靠谱的答案。这道题其实很有难度,涉及的知识点有jvm内存分配、作用域...

    乔戈里
  • 某团面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    这道题其实很有难度,涉及的知识点有jvm内存分配、作用域、gc等,不是简单的是与否的问题。

    良月柒
  • 美团面试题:JVM堆内存溢出后,其他线程是否可继续工作?

    最近网上出现一个美团面试题:“一个线程OOM后,其他线程还能运行吗?”。我看网上出现了很多不靠谱的答案。这道题其实很有难度,涉及的知识点有jvm内存分配、作用域...

    Spark学习技巧
  • 如何理解和使用Python中的列表

    Python有6个序列的内置类型,但最常见的是列表和元组。今天我们就来讲讲列表。

    小土豆Yuki
  • 你还在为怎么查看字节码指令而担忧吗?

    我们平时编码过程中,可能很少去查看 Java 文件编译后的字节码指令。但是,不管你是因为对技术非常热爱,喜欢刨根问底,还是想在别人面前装X 。我认为,都非常有必...

    烟雨星空
  • java SE学习之线程同步(详细介绍)

           java程序中可以允许存在多个线程,但在处理多线程问题时,必须注意这样一个问题:               当两个或多个线程同时访问同一个变...

    Gxjun

扫码关注云+社区

领取腾讯云代金券