最近看到一道面试题字符串两个线程交替输出,简单写一下做个记录,先用到的就是wait和notify,初始代码如下:
package test.thread.wait;
public class Wait1 {
private String str1 = "ABCDEFGH";
private String str2 = "abcdef";
/**
* 用于控制字符串长度不一致的flag
*/
private volatile boolean flag = false;
public synchronized void m1() throws InterruptedException {
int length = str1.length();
int i = 0;
while (i < length) {
System.out.println(str1.charAt(i));
if (!flag) {
this.notify();
// 最后一个就不wait了,直接结束
if (i < length - 1) {
this.wait();
}
}
if (i == length - 1) {
flag = true;
}
i++;
}
}
public synchronized void m2() throws InterruptedException {
int length = str2.length();
int i = 0;
while (i {
try {
wait1.m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
wait1.m2();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
当然,也可以使用Lock的await,condition 或者LockSupport的park,unpark实现。
贴上代码 Lock的await,condition 的实现:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
private final ReentrantLock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private String str1 = "ABCDEFGH";
private String str2 = "abcdef";
/**
* 用于控制字符串长度不一致的flag
*/
private volatile boolean flag = false;
public void m1() throws InterruptedException {
int length = str1.length();
int i = 0;
while (i < length) {
System.out.println(str1.charAt(i));
if (!flag) {
try {
lock.lock();
condition2.signal();
if (i < length - 1) {
condition1.await();
}
} finally {
lock.unlock();
}
}
if (i == length - 1) {
flag = true;
}
i++;
}
}
public synchronized void m2() throws InterruptedException {
int length = str2.length();
int i = 0;
while (i < length) {
System.out.println(str2.charAt(i));
if (!flag) {
try {
lock.lock();
condition1.signal();
if (i < length - 1) {
condition2.await();
}
} finally {
lock.unlock();
}
}
if (i == length - 1) {
flag = true;
}
i++;
}
}
public static void main(String[] args) {
TestLock testLock = new TestLock();
Thread t1 = new Thread(() -> {
try {
testLock.m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
testLock.m2();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
LockSupport的park,unpark实现:
import java.util.concurrent.locks.LockSupport;
public class LockSupport1 {
private static String str1 = "ABCDEFGH";
private static String str2 = "abcdef";
/**
* 用于控制字符串长度不一致的flag
*/
private volatile static boolean flag;
private static Thread t1, t2;
public static void m1() {
int i = 0;
int length = str1.length();
while (i < length) {
System.out.println(str1.charAt(i));
LockSupport.unpark(t2);
if (!flag) {
if (i < length - 1) {
LockSupport.park();
}
}
if (i == length - 1) {
flag = true;
}
i++;
}
}
public static void m2() {
int i = 0;
int length = str2.length();
while (i < length) {
if (!flag) {
// 最后一次时候还是要等待另外一个线程唤醒,否则会直接输出了
LockSupport.park();
}
System.out.println(str2.charAt(i));
if (i == length - 1) {
flag = true;
}
LockSupport.unpark(t1);
i++;
}
}
public static void main(String[] args) {
t1 = new Thread(() -> {
LockSupport1.m1();
});
t2 = new Thread(() -> {
LockSupport1.m2();
});
t1.start();
t2.start();
}
}