线程交替打印的几种实现方式
- synchronized提供的wait、notify
- LockSupport的park、unpark
- ReentrantLock和condition
- 基于cas机制实现线程交替打印
- TransferQueue实现
synchronized提供的wait、notify
/**
* @author yanyapan
*/
public class WaitNotifyToPrint {
public static void main(String[] args) {
final Object object = new Object();
char[] a1 = "1234567".toCharArray();
char[] a2 = "ABCDEFG".toCharArray();
new Thread(() -> {
synchronized (object){
for(char c : a1){
System.out.print(c);
try{
object.notify();
object.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
object.notify();//避免有线程未被唤醒
}
},"t1").start();
new Thread(() -> {
synchronized (object){
for(char c : a2){
System.out.print(c);
try{
object.notify();
object.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
object.notify();//避免有线程未被唤醒
}
},"t2").start();
}
}
LockSupport的park、unpark
/**
* @author yanyapan
*/
public class LockSupportToPrint {
private static Thread t1;
private static Thread t2;
public static void main(String[] args) {
char[] a1 = "1234567".toCharArray();
char[] a2 = "ABCDEFG".toCharArray();
t1 = new Thread(() -> {
for(char c : a1){
System.out.print(c);
LockSupport.unpark(t2);//释放t2线程 设置锁标志位
LockSupport.park();//阻塞当前线程
}
},"t1");
t2 = new Thread(() -> {
for(char c : a2){
LockSupport.park();//阻塞当前线程
System.out.print(c);
LockSupport.unpark(t1);//释放t1线程
}
},"t2");
t1.start();
t2.start();
}
}
ReentrantLock和condition
/**
* @author yanyapan
*/
public class LockConditionToPrint {
public static void main(String[] args) {
char[] a1 = "1234567".toCharArray();
char[] a2 = "ABCDEFG".toCharArray();
Lock lock = new ReentrantLock();//锁
Condition t1 = lock.newCondition();//t1队列
Condition t2 = lock.newCondition();//t2队列
new Thread(() ->{
try{
lock.lock();
for(char c : a1){
System.out.print(c);
t2.signal();//唤醒t2队列中等待的线程
t1.await();//进入t1队列自旋等待
}
t1.signal();//避免有线程未被唤醒
t2.signal();//避免有线程未被唤醒
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
},"t1").start();
new Thread(() ->{
try{
lock.lock();
for(char c : a2){
System.out.print(c);
t1.signal();//唤醒t1队列中等待的线程
t2.await();//进入t2队列自旋等待
}
t1.signal();//避免有线程未被唤醒
t2.signal();//避免有线程未被唤醒
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
},"t2").start();
}
}
基于cas机制实现线程交替打印
/**
* @author yanyapan
*/
public class CasToPrint {
enum ReadyToRun{
T1,T2
}
private static volatile ReadyToRun readyToRun = ReadyToRun.T1;
public static void main(String[] args) {
char[] a1 = "1234567".toCharArray();
char[] a2 = "ABCDEFG".toCharArray();
new Thread(() ->{
for(char c : a1){
while (readyToRun != ReadyToRun.T1){}//cas自旋
System.out.print(c);
readyToRun = ReadyToRun.T2;//线程可见性
}
},"t1").start();
new Thread(() ->{
for(char c : a2){
while (readyToRun != ReadyToRun.T2){}//cas自旋
System.out.print(c);
readyToRun = ReadyToRun.T1;//线程可见性
}
},"t2").start();
}
}
TransferQueue实现
/**
* @author yanyapan
*/
public class TransferQueueToPrint {
public static void main(String[] args) {
char[] a1 = "1234567".toCharArray();
char[] a2 = "ABCDEFG".toCharArray();
TransferQueue<Character> queue = new LinkedTransferQueue<>();
new Thread(() ->{
try{
for(char c : a1){
System.out.print(queue.take());
queue.transfer(c);
}
}catch (InterruptedException e){
e.printStackTrace();
}
},"t1").start();
new Thread(() ->{
try{
for(char c : a2){
queue.transfer(c);
System.out.print(queue.take());
}
}catch (InterruptedException e){
e.printStackTrace();
}
},"t2").start();
}
}
总结:
- 需要对jdk底层有深刻的理解,如aqs、synchronized的锁升级过程、cas机制(jdk中atomic包中大量使用)
- 对jdk中提供的并发数据结构学习掌握
- 理解原理才能写出对的代码