多线程之交替打印数字与字母案例

编写一段代码,创建2个线程,一个线程循环输出123...90123...,另一个线程循环输出ABC...ZABC...,要求控制台最终输出效果为1A2B3C4D5E...。

方案1:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class NumberCharTest {

    public static void main(String[] args) {

        NumberChar numberChar = new NumberChar();

        new Thread(() -> {
            numberChar.printNumber();

        }, "数字").start();

        new Thread(() -> {
            numberChar.printChar();

        }, "字符").start();

    }

}


class NumberChar {

    private int startNum = 1;

    private char startChar = 'A';

    private ReentrantLock lock = new ReentrantLock();

    Condition numCondition = lock.newCondition();

    Condition charCondition = lock.newCondition();


    public void printNumber() {

        while (true) {

            try {
                lock.lock();
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + ":" + startNum++);
                charCondition.signal();
                numCondition.await();
                if (startNum == 10) {
                    //重置为 0
                    startNum = 0;
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public void printChar() {

        while (true) {
            try {
                lock.lock();
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + ":" + startChar++);
                numCondition.signal();
                charCondition.await()
                //此处释放锁
                //System.sout.println("开始释放锁");
                if (startChar == 'Z' + 1) {
                    startChar = 'A';
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
            //如果线程阻塞或者try/finally包围在while(true)循环外将不会执行finally里的代码。
            //System.out.println("---字符finally执行---");
                lock.unlock();
            }
        }
    }

}

方案2:

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class NumberCharTest2 {
    public static void main(String[] args) {
        List arr = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
        List arr2 = Arrays.asList('A', 'B', 'C', 'D', 'E', 'F', 'G');
//        List arr3 = Arrays.asList("a","b","c","d","e");


        ReentrantLock reentrantLock = new ReentrantLock();
        Condition condition1 = reentrantLock.newCondition();
        Condition condition2 = reentrantLock.newCondition();
        Condition condition3 = reentrantLock.newCondition();
        Task task = new Task(arr, reentrantLock, condition1, condition2);
        Task task2 = new Task(arr2, reentrantLock, condition2, condition1);
//        Task task3 = new Task(arr3,reentrantLock,condition3,condition1);

        Thread t1 = new Thread(task, "线程1");
        Thread t2 = new Thread(task2, "线程2");
//        Thread t3 = new Thread(task3,"线程3");
        t1.start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
//        try {
//            TimeUnit.SECONDS.sleep(1);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        t3.start();
    }
}

class Task implements Runnable {
    private List objs;
    private ReentrantLock reentrantLock;
    private Condition currentCondition;
    private Condition otherCondition;

    public Task(List objs, ReentrantLock reentrantLock, Condition currentCondition, Condition otherCondition) {
        this.objs = objs;
        this.reentrantLock = reentrantLock;
        this.currentCondition = currentCondition;
        this.otherCondition = otherCondition;
    }

    @Override
    public void run() {
        while (true) {
            reentrantLock.lock();
            for (int i = 0; i < objs.size(); i++) {
                System.out.println(Thread.currentThread().getName() + "输出:" + objs.get(i));
                try {
                    //此处signal()方法一定要放await()前面,不然当前线程刚释放锁进入等待状态,
                    // 另外一个线程进来也会变成等待状态,程序将会一直等待下去
                    otherCondition.signal();
                    currentCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
            //如果线程都不是等待状态,那么finally中代码会执行。
            //System.out.println("---finally代码块执行---");
                reentrantLock.unlock();
            }
        }
    }
}

2种方案总结

其实这2种方案都差不多,第一种更加清晰一点,第二种便于控制,灵活一点,能够很方便的再加一个新的线程进来进行相应的操作。

你可能感兴趣的:(多线程)