要求用线程打印 A1B2C3D4…Z26
思路:
使用线程打印A1B2…Z26,需要2个线程交替打印,这样就需要2个线程交替运行,我们可以使用
①同步锁synchronized加上awit和notify方法。
②LockSupport的park和unpark方法。
③还有很多其他锁都可以玩 可以看下我后续一些锁的更新
①synchronized
public class Test3 {
public static void main(String[] args) {
//启动2个线程交替打印
Object o = new Object();
new Thread(() -> {
synchronized (o) {
for (int i = 1; i < 27; i++) {
char c = (char) (96 + i);
String s = String.valueOf(c).toUpperCase();
System.out.print(s);
try {
o.wait(); //@1
o.notify(); //@2
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "t1").start();
new Thread(() -> {
synchronized (o) {
for (int i = 1; i < 27; i++) {
System.out.print(i);
try {
o.notify(); //@3
o.wait(); //@4
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "t2").start();
}
}
解释 :
① t1线程执行@1,打印A,此时调用wait(),此时释放锁并且阻塞线程t1。
② t2拿到锁o,打印1,然后就要唤醒线程t1@3,此时notify()是不释放锁的t1肯定拿不到锁,所以需要再次调用wait() @4释放锁且阻塞线程t2。
③继续执行@2,唤醒t2同时不释放锁,继续执行下一步t1B,然后再@1wait()。
④ 循环执行。
线程之间相互阻塞唤醒,要想运行都是必须要拿到锁的,所以wait()和notify()对于锁的释放要了解,才能确定使用位置
②LockSupport
public class Test4 {
private static Thread t1;
private static Thread t2;
public static void main(String[] args) {
t1= new Thread(() -> {
for (int i = 1; i < 27; i++) {
char c = (char) (96 + i);
String s = String.valueOf(c).toUpperCase();
System.out.print(s);
LockSupport.park(t1); // @1
LockSupport.unpark(t2); // @2
}
});
t2= new Thread(() -> {
for (int i = 1; i <= 26; i++) {
LockSupport.unpark(t1); // @3
System.out.print(i);
LockSupport.park(t2); // @4
}
});
t1.start();
t2.start();
}
解释 :
① 必须先启动线程1,打印A之后,调用park(t1)阻塞t1;
② t2启动,我们可以先把t1给释放即@3,当然它再线程等待队列中等t2执行。后面调用我们业务 打印
③ 调用@4阻塞当前t2,此时等待队列中的t1就继续执行,执行@2,把t2在放入等待队列中,然后继续自己业务,等到下次阻塞
Locksupport采用的是无锁概念,很方便的阻塞和释放线程,思路想好具体流程和业务顺序即可