JAVA 两个线程交替打印奇偶数

涉及到线程间的通信问题,在程序层面来说可以通过线程的等待和唤醒来实现线程之间的通知。

先创建奇偶线程类


    public class OddEvenThread implements Runnable {

        private volatile int i = 0;

        private Object lock = new Object();

        @Override
        public void run() {
            for(;;) {

                synchronized (lock) {
                    if (i > 100) {
                        break;
                    }

                    if ((i % 2) == 0) {
                        System.out.println("even: " + i++);
                    } else {
                        System.out.println("odd: " + i++);
                    }

                    try {
                        // 唤醒所有锁住这个对象的线程 让出锁
                        lock.notifyAll();
                        // 后续再锁住自己这个线程
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }

    }

调用的代码很简单

    OddEvenThread oddEvenThread = new OddEvenThread();
    new Thread(oddEvenThread).start();
    new Thread(oddEvenThread).start();

打印完数字后,让出锁,是其他线程可以运行,最后锁住自己的线程,等待唤醒

后续想想,还有其他的方式,可以尝试使用concurrent包里面的lock来枷锁,同理也是可以完成这个功能的
只需要略微修改一下lock的方式

    public class OddEvenThread implements Runnable {

        private volatile int i = 0;

        private Lock lock = new ReentrantLock();

        private Condition condition = lock.newCondition();

        @Override
        public void run() {
            for(;;) {

                try {

                    lock.lock();
                    if (i > 100) {
                        break;
                    }

                    if ((i % 2) == 0) {
                        System.out.println("even: " + i++);
                    } else {
                        System.out.println("odd: " + i++);
                    }

                    try {
                        condition.signalAll();
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } finally {
                    lock.unlock();
                }
            }

        }

    }

上面两种实现方式都是比较常见的线程等待,也可以利用阻塞队列来实现线程间的通信,采用的是及时同步队列SynnhronousQueue

    private SynchronousQueue<Integer> oddSynchronousQueue = new SynchronousQueue();

    private SynchronousQueue<Integer> evenSynchronousQueue = new SynchronousQueue();

    public class OddThread implements Runnable {

        @Override
        public void run() {
            for(;;) {

                try {
                    int i = oddSynchronousQueue.take();
                    System.out.println("odd: " + i++);
                    evenSynchronousQueue.put(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public class EvenThread implements Runnable {

        @Override
        public void run() {
            for(;;) {
                try {
                    int i = evenSynchronousQueue.take();
                    System.out.println("even: " + i++);
                    oddSynchronousQueue.put(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public void init() throws InterruptedException {
        OddThread oddThread = new OddThread();
        EvenThread evenThread = new EvenThread();
        new Thread(oddThread).start();
        new Thread(evenThread).start();
        oddSynchronousQueue.put(1);
    }

其中一个线程获取到值后,会给另外的线程通信,同时阻塞自己所在的线程。
这样就可以做到交替传输数据,免去了唤醒线程这种耗时操作。