两个线程交替打印1-100

2,451 阅读1分钟

要求

多线程交替打印1-100

分析

要求两个线程,一个打印奇数,一个打印偶数。考察线程同步和锁相关知识点。

实现

方法1

通过synchronized+对象wait()和notify()

public class Test {

    public static void main(String[] args) {
        PrintRun printRun = new PrintRun();
        Thread thread1 = new Thread(printRun);
        thread1.setName("线程1");
        Thread thread2 = new Thread(printRun);
        thread2.setName("线程2");
        thread1.start();
        thread2.start();
    }

    public static class PrintRun implements Runnable{
        volatile int i = 1;  //需要定义为volatile,保证线程可见性
        @Override
        public void run() {
            while (true){
                synchronized (this){
                    notify(); //调用notify()不会直接唤醒下一个线程,需要等synchronized代码块执行完
                    System.out.println(Thread.currentThread().getName()+"打印:"+i);
                    i++;
                    if (i < 100){
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else {
                        break;
                    }
                }
            }
        }
    }
}

方法2

使用Lock+Condition

public class Test {
    
    public static void main(String[] args) {
        PrintRun printRun = new PrintRun();
        Thread thread1 = new Thread(printRun::run);
        Thread thread2 = new Thread(printRun::run);
        thread1.setName("线程1");
        thread2.setName("线程2");
        thread1.start();
        thread2.start();
    }

    public static class PrintRun{
        private final AtomicInteger count = new AtomicInteger(1); //也可替换成volatile
        private final Lock lock = new ReentrantLock();
        private final Condition single = lock.newCondition();
        private final Condition twin = lock.newCondition();
        public void run(){
            lock.lock();
            try {
                while (count.get() <= 100){
                    if (count.get() % 2 == 1){
                        System.out.println(Thread.currentThread().getName()+"打印:"+count.get());
                        twin.signal(); //不会真正唤醒twin,需要等待single释放锁
                        if (count.incrementAndGet() <= 100){
                            single.await(); //single等待并释放锁
                        }
                    }else {
                        System.out.println(Thread.currentThread().getName()+"打印:"+count.get());
                        single.signal();
                        if (count.incrementAndGet() <= 100){
                            twin.await();
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}