这是我去年阿里笔试的时候遇到的题,要求三个线程交替打印 ‘a,l,i’(当时根本没来得及做),这次翻出来看看原来好简单(现在看那时候的五题都挺简单的,还是那时候准备的太少了,活该被刷)(现在也准备的少…)
关于线程的站内链接:Java多线程-1-线程安全与锁,Java多线程-2-可重入锁以及Synchronized的其他基本特性
两个线程交替打印奇偶数
先看两个线程交替运行
1 | public class Work2 { |
运行结果:
1 | t1 1 |
该实现的原理也非常简单,定义一个对象,因为一个对象有且只有一个锁,所以让两个线程循环让此对象解锁->加锁,从而达到线程交替运行的目的。
创建三个线程交替循环打印’A,B,C’
法一:synchronized
主要的思想就是,为了控制执行的顺序,必须要先持有prev锁,也就是前一个线程要释放自身对象锁,再去申请自身对象锁,两者兼备时打印字母,之后首先调用self.notifyAll()释放自身对象锁,唤醒下一个等待线程,再调用prev.wait()释放prev对象锁,终止当前线程,等待循环结束后再次被唤醒。程序运行的主要过程就是A线程最先运行,持有C,A对象锁,后释放A,C锁,唤醒B。线程B等待A锁,再申请B锁,后打印B,再释放B,A锁,唤醒C,线程C等待B锁,再申请C锁,后打印C,再释放C,B锁,唤醒A……
1 | public class ABC { |
法二:ReentrantLock
使用ReentrantLock替代synchronized。ReentrantLock是一个可重入且独占式的锁,它具有与使用synchronized监视器锁相同的基本行为和语义,但与synchronized关键字相比,它更灵活、更强大,增加了轮询、超时、中断等高级功能。ReentrantLock,顾名思义,它是支持可重入锁的锁,是一种递归无阻塞的同步机制。除此之外,该锁还支持获取锁时的公平和非公平选择。
1 | package com.xwl; |