本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。

1) 线程通信

题目:实现一个容器,提供两个方法,add / size,写两个线程,线程 1 添加 10 个元素到容器中,线程 2 实现监控元素的个数,当个数到 5 个时,线程 2 给出提示并结束。

1.1) 思路:

首先会面临两个问题,add / size 函数的一致性问题,和容器的线程见可见性问题

  • 容器选择:两种选择方案,使用普通 list,给 add / size 上锁;或者用 Collections 来生成同步容器
  • 可见性问题:遇到可见性问题第一个会想到 volatile,但是 volatile 不能保证元素内部发生改变时的线程间可见性问题。处理方式多种:notify、CountDownLatch、LockSupport 等等,Semaphore 都行。

LockSupport 版,代码少哈哈哈哈哈哈哈哈

public class Thread_Notify {

    List<Object> list = Collections.synchronizedList(new ArrayList<>());
    static Thread a;
    static Thread b;

    public void add(Object o) {
        list.add(o);
    }

    public int size() {
        return list.size();
    }

    public static void main(String[] args) {
        Thread_Notify instance = new Thread_Notify();

        a = new Thread(() -> {
        LockSupport.park();
        System.out.println("=====5");
        LockSupport.unpark(a);
        });

        b = new Thread(() -> {
        for (int i = 1; i <= 10; i++) {
            instance.add(i);
            System.out.println(i);
            if (5 == i) {
            LockSupport.unpark(b);
            LockSupport.park();
            }
        }
        });

        a.start();
        b.start();
    }
}

2) 线程阻塞

题目:写一个固定容量同步容器,拥有 put 和 get 方法,以及 getCount 方法,能够支持 2 个生产者线程和 10 个消费者线程的阻塞调用。

2.1) 思路

这题本质上是考知识面,是否知道 Condition,可以给容器加个泛型装逼 -。-

public class ThreadCondition {

    private final int MAX_SIZE = 10;
    private final LinkedList<Object> list = new LinkedList<>();
    private int count = 0;

    private Lock lock = new ReentrantLock();
    Condition producer = lock.newCondition();
    Condition consumer = lock.newCondition();

    public void put(Object o) {
        try {
        lock.lock();
        while (MAX_SIZE == list.size()) producer.await();

        list.add(o);
        ++count;
        consumer.signalAll();
        } catch (InterruptedException e) {
        e.printStackTrace();
        } finally {
        lock.unlock();
        }
    }

    public Object get() {
        Object result = null;
        try {
        lock.lock();
        while (0 == count) consumer.await();

        result = list.removeFirst();
        --count;
        producer.signalAll();
        } catch (InterruptedException e) {
        e.printStackTrace();
        } finally {
        lock.unlock();
        }
        return result;
    }

    public static void main(String[] args) {
        ThreadCondition list = new ThreadCondition();

        for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            for (int j = 0; j < 5; j++) {
            System.out.println(list.get());
            }
        }).start();
        }

        for (int i = 0; i < 2; i++) {
        new Thread(() -> {
            for (int j = 0; j < 25; j++) {
            list.put(Thread.currentThread().getName() + " - " + j);
            }
        }, "Producer " + i).start();
        }
    }
}