JAVA将A1B2C3,多线程打印A1B2C3的几种方式

synchronized方式

public class A1B2C3Synchronized {

private static Object o = new Object ();

private static volatile boolean flag = false;

public static void main(String[] args) {

char[] chars1 = "ABCDEF".toCharArray ();

char[] chars2 = "123456".toCharArray ();

new Thread (() -> {

synchronized (o) {

while(flag){}

for (int i = 0; i < chars1.length; i++) {

System.out.print (chars1[i]);

flag = true;

//唤醒等待线程,只有两个线程,所以这里唤醒的事另一个线程

o.notify ();

try {

o.wait ();

} catch (InterruptedException e) {

e.printStackTrace ();

}

}

}

}).start ();

new Thread (() -> {

synchronized (o) {

while(!flag){}

for (int i = 0; i < chars2.length; i++) {

System.out.println (chars2[i]);

//唤醒等待线程,只有两个线程,所以这里唤醒的事另一个线程

o.notify ();

try {

o.wait ();

} catch (InterruptedException e) {

e.printStackTrace ();

}

}

}

}).start ();

}

}

LockSupport方式

public class A1B2C3LockSupport {

private static Object o = new Object ();

private static Thread t1, t2;

private static volatile boolean flag = false;

public static void main(String[] args) {

char[] chars1 = "ABCDEF".toCharArray ();

char[] chars2 = "123456".toCharArray ();

t1 = new Thread (() -> {

while(flag){}

for (int i = 0; i < chars1.length; i++) {

LockSupport.unpark (t2);

System.out.print (chars1[i]);

flag = true;

LockSupport.park ();

}

});

t2 = new Thread (() -> {

while(!flag){}

for (int i = 0; i < chars2.length; i++) {

LockSupport.park ();

System.out.println (chars2[i]);

LockSupport.unpark (t1);

}

});

t1.start ();

t2.start ();

}

}

CAS的两种方式(1)

public class A1B2C3CAS {

private static Object o = new Object ();

private static Thread t1, t2;

private static volatile boolean flag = false;

public static void main(String[] args) {

char[] chars1 = "ABCDEF".toCharArray ();

char[] chars2 = "123456".toCharArray ();

//利用volatile自旋,也可以使用AtomicInteger

t1 = new Thread (() -> {

for (int i = 0; i < chars1.length; i++) {

while (flag) {}

System.out.print (chars1[i]);

flag = true;

}

});

t2 = new Thread (() -> {

for (int i = 0; i < chars1.length; i++) {

while (!flag) {}

System.out.println (chars2[i]);

flag = false;

}

});

t1.start ();

t2.start ();

}

}

CAS的两种方式(2)

public class A1B2C3CAS1 {

static Unsafe unsafe;

int flag = 0;

static long headOffset ;

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

unsafe = UnsafeInit ();

//偏移量,compareAndSwapObject方法的第二个参数

headOffset = unsafe.objectFieldOffset (A1B2C3CAS1.class.getDeclaredField ("flag"));

char[] chars1 = "ABCDEF".toCharArray ();

char[] chars2 = "123456".toCharArray ();

new Thread (() -> {

for (int i = 0; i < chars1.length; i++) {

//两次cas为了保证两个线程的打印顺序

while (!unsafe.compareAndSwapInt (A1B2C3CAS1.class, headOffset, 0,2)){}

System.out.print (chars1[i]);

unsafe.compareAndSwapInt (A1B2C3CAS1.class, headOffset, 2,1);

}

}).start ();

new Thread (() -> {

for (int i = 0; i < chars2.length; i++) {

while (!unsafe.compareAndSwapInt (A1B2C3CAS1.class, headOffset, 1,2)){}

System.out.println (chars2[i]);

unsafe.compareAndSwapInt (A1B2C3CAS1.class, headOffset, 2,0);

}

}).start ();

}

public static Unsafe UnsafeInit() throws NoSuchFieldException, IllegalAccessException {

//创建unsafe

Class> clazz = Unsafe.class;

Field f = clazz.getDeclaredField ("theUnsafe");

f.setAccessible (true);

return ( Unsafe ) f.get (clazz);

}

}

阻塞队列方式

public class A1B2C3BlockingQueue {

/**

* 很多队列都能实现,这里使用数组阻塞队列举例

*/

static BlockingQueue q1 = new ArrayBlockingQueue (1);

static BlockingQueue q2 = new ArrayBlockingQueue (1);

public static void main(String[] args) {

char[] chars1 = "ABCDEF".toCharArray ();

char[] chars2 = "123456".toCharArray ();

new Thread (() -> {

for (int i = 0; i < chars1.length; i++) {

try {

System.out.print (q1.take ());

q2.put (chars2[i]);

} catch (InterruptedException e) {

e.printStackTrace ();

}

}

}).start ();

new Thread (() -> {

for (int i = 0; i < chars2.length; i++) {

try {

q1.put (chars1[i]);

System.out.println (q2.take ());

} catch (InterruptedException e) {

e.printStackTrace ();

}

}

}).start ();

}

}

等待队列方式

/**

* 个人认为等待队列稍微难理解一点

*/

public class A1B2C3Lock {

static ReentrantLock reentrantLock;

static volatile boolean flag = true;

public static void main(String[] args) {

char[] chars1 = "ABCDEF".toCharArray ();

char[] chars2 = "123456".toCharArray ();

reentrantLock = new ReentrantLock ();

Condition condition = reentrantLock.newCondition ();

new Thread (() -> {

//利用flag保证线程1在线程2之前执行

while(!flag){}

flag = false;

try {

//线程1先获取锁

reentrantLock.lock ();

for (int i = 0; i < chars1.length; i++) {

//将等待队列线程同步到CLH队列

condition.signal ();

System.out.print (chars1[i]);

//将线程1放到等待队列,并唤醒CLH队列head的下一个node代表的线程唤醒

condition.await ();

}

} catch (InterruptedException e) {

e.printStackTrace ();

} finally {

/**为什么加这一段代码,t2是在打印F6的6以后,通过await方法将t2存放到等待队列中,并

唤醒t1线程,所以此时CLH队列中只有t1,而线程被唤醒只能是在CLH队列中,这段代码就是将t2

线程从等待队列中转移到CLH队列,通过unlock将t2唤醒*/

condition.signal ();

reentrantLock.unlock ();

}

}, "t1").start ();

new Thread (() -> {

while(flag){}

try {

reentrantLock.lock ();

for (int i = 0; i < chars2.length; i++) {

condition.signal ();

System.out.println (chars2[i]);

condition.await ();

}

} catch (InterruptedException e) {

e.printStackTrace ();

} finally {

reentrantLock.unlock ();

}

}, "t2").start ();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值