两个线程依次输出list集合里边的数

package com.sohu.smc.base.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by pengjia on 2016/8/23.
 */
public class NumberPrint implements Runnable {
    private int state = 1;
    // 使用lock做锁
    private ReentrantLock lock = new ReentrantLock();
    // 获得lock锁的3个分支条件
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private static List<Integer> list1;
    private static List<Integer> list2;
    static {
        list1 = new ArrayList<Integer>();
        list2 = new ArrayList<Integer>();
        list1.add(1);
        list1.add(3);
        list1.add(5);
        list1.add(7);
        list2.add(2);
        list2.add(4);
        list2.add(6);
        list2.add(8);
    }


    @Override
    public void run() {
        new Thread(new Runnable() {
            public void run() {
                for (int i1:list1) {
                    try {
                        // 线程1获得lock锁后, 其他线程将无法进入需要lock锁的代码块.
                        // 在lock.lock()和lock.unlock()之间的代码相当于使用了synchronized(lock){}
                        lock.lock();
                        while (state != 1){
                            try {
                                // 线程1竞争到了lock, 但是发现state不为1, 说明此时还未轮到线程1打印.
                                // 因此线程1将在c1上wait
                                // 与解法一不同的是, 三个线程并非在同一个对象上wait, 也不由同一个对象唤醒
                                c1.await();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }

                        // 如果线程1竞争到了lock, 也通过了state判定, 将执行打印任务
                        System.out.println(Thread.currentThread().getName() + ": " + i1);
                        System.out.println();
                        // 打印完成后将state赋值为2, 表示下一次的打印任务将由线程2执行
                        state = 2;
                        // 唤醒在c2分支上wait的线程2
                        c2.signal();
                    } finally {
                        // 打印任务执行完成后需要确保锁被释放, 因此将释放锁的代码放在finally中
                        lock.unlock();
                    }
                }
            }
        }, "线程1").start();

        new Thread(new Runnable() {
            public void run() {
                for (int i2:list2) {
                    try {
                        lock.lock();
                        while (state != 2){
                            try {
                                c2.await();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + ": " + i2++);
                        System.out.println();
                        state = 1;
                        c1.signal();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }, "线程2").start();
    }

    public static void main(String[] args) {
        new NumberPrint().run();
    }
}

点赞