先介绍一种synchronized方式的实现:
提到交替打印,用到synchronized,不得不提到wait和notify,当前线程打印出当前数据之后,wait之前,需要通知其他,我即将wait,你可以继续运行了,好了,话不多说,直接上代码:
1 public class T02_ReentrantLock2 {
2
3 synchronized void s1() {
4 String abc = "abcdefghijklmnopqrstuvwxyz";
5 String[] a = abc.split("");
6 for(String value : a) {
7 System.out.println(value);
8 this.notify();
9 try {
10 this.wait();
11 Thread.sleep(100);// 防止打印速度过快导致混乱
12 } catch (InterruptedException e) {
13 e.printStackTrace();
14 }
15 }
16
17 }
18 synchronized void n1() {
19
20 for(int i = 1; i< 27; i++) {
21 System.out.println(i);
22 this.notify();
23 try {
24 this.wait();
25 Thread.sleep(100);// 防止打印速度过快导致混乱
26 } catch (InterruptedException e) {
27 e.printStackTrace();
28 }
29 }
30
31 }
32
33 public static void main(String[] args) {
34 T02_ReentrantLock2 rl = new T02_ReentrantLock2();
35 Thread t1 = new Thread(rl::s1);
36 Thread t2 = new Thread(rl::n1);
37 t1.start();
38 t2.start();
39 }
40 }
其实实现很简单,最主要的点,就是什么时候wait,什么时候notify,正常情况下,他们是交替出现的,目的都是currentThread wait之前,唤起其他线程。
接下来是第二种,也是稍微复杂点的方式,直接使用ReentrantLock,进一步使用Condition,Condition相当于一个容器,在一个Lock中New多少个Condition,就相当于创建了多少个等待队列,因此,通过一个lock,两个不同的线程,两个Condition,可以轻松实现以上需求,需要注意的是,每次lock后需要及时unlock。
public class T01_ReentrantLock1 {
public static boolean isInteger(String str) {
Pattern pattern = Pattern.compile("[0-9]*");
return pattern.matcher(str).matches();
}
private static Lock lock = new ReentrantLock();
private static List<String> a = new ArrayList<String>(
Arrays.asList("a", "1", "b", "2", "c", "3", "d", "4", "e", "5", "f", "6", "g", "7", "h", "8", "i", "9", "j",
"10", "k", "11", "l", "12", "m", "13", "n", "14", "o", "15", "p", "16", "q", "17", "r", "18", "s",
"19", "t", "20", "u", "21", "v", "22", "w", "23", "x", "24", "y", "25", "z", "26"));
private static volatile int i = 0;
public static void main(String[] args) {
Condition number = lock.newCondition();
Condition abcString = lock.newCondition();
new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
while(i < a.size()){
lock.lock();
try {
if (isInteger(a.get(i)) ) {
abcString.await();
}
if(i < a.size()) {
System.out.println(Thread.currentThread() + " : " + a.get(i));
i++;
number.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}, "String").start();
new Thread(() -> {
try {
Thread.sleep(100);
while (i < a.size()) {
lock.lock();
// 必须带条件才会相互切换,且判断带条件必须是同一个对象
if (!isInteger(a.get(i))) {
number.await();
}
// 必须在打印之前判断下,是否另外一个线程i++后还小于数组,否则数组下表越界
if (i < a.size()) {
System.out.println(Thread.currentThread() + " : " + a.get(i));
i++;
abcString.signal();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
, "num").start();
}
}