0、面试题
实现:第一个线程从1到26,第二个线程从A到Z,然后要让这两个线程做到同时运行,交替输出,顺序打印。
输出结果:1A2B3C4D5E6F7G8H9I10J11K12L13M14N15O16P17Q18R19S20T21U22V23W24X25Y26Z
你有哪些玩法?
1、LockSupport
public class LockSupportDemo {
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
t1 = new Thread(() -> {
for (String num : nums) {
System.out.print(num);
LockSupport.unpark(t2);//唤醒 t2
LockSupport.park();// t1 阻塞
}
}, "T1");
t2 = new Thread(() -> {
for (String letter : letters) {
LockSupport.park();// t2 阻塞
System.out.print(letter);
LockSupport.unpark(t1);//唤醒 t1
}
}, "T2");
t1.start();
t2.start();
}
}
2、synchronized+wait+notify
public class WaitNotifyDemo {
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
final Object o = new Object();
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
t1 = new Thread(() -> {
synchronized (o) {
try {
for (String num : nums) {
System.out.print(num);
o.notify();
o.wait(); //阻塞 t1
}
} catch (InterruptedException e) {
e.printStackTrace();
}
o.notify();//必须,否则无法停止程序
}
}, "T1");
t2 = new Thread(() -> {
synchronized (o) {
try {
for (String letter : letters) {
System.out.print(letter);
o.notify();
o.wait(); //阻塞 t2
}
} catch (InterruptedException e) {
e.printStackTrace();
}
o.notify(); //必须,否则无法停止程序
}
}, "T2");
t1.start();
t2.start();
}
}
3、ReentrantLock + 1个Condition
public class LockConditionDemo {
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
t1 = new Thread(() -> {
lock.lock();
try {
for (String num : nums) {
System.out.print(num);
condition.signal();
condition.await();
}
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "T1");
t2 = new Thread(() -> {
lock.lock();
try {
for (String letter : letters) {
System.out.print(letter);
condition.signal();
condition.await();
}
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "T2");
t1.start();
t2.start();
}
}
4、ReentrantLock + 2个Condition
public class LockConditionDemo2 {
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
ReentrantLock lock = new ReentrantLock();
Condition conditionT1 = lock.newCondition();
Condition conditionT2 = lock.newCondition();
t1 = new Thread(() -> {
lock.lock();
try {
for (String num : nums) {
System.out.print(num);
conditionT2.signal();
conditionT1.await();
}
conditionT2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "T1");
t2 = new Thread(() -> {
lock.lock();
try {
for (String letter : letters) {
System.out.print(letter);
conditionT1.signal();
conditionT2.await();
}
conditionT1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "T2");
t1.start();
t2.start();
}
}
5、自定义CAS实现
public class CASDemo {
enum ReadyToRun {T1, T2}
static volatile ReadyToRun r = ReadyToRun.T1;
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
t1 = new Thread(() -> {
for (String num : nums) {
while (r != ReadyToRun.T1) {
}
System.out.print(num);
r = ReadyToRun.T2;
}
}, "T1");
t2 = new Thread(() -> {
for (String letter : letters) {
while (r != ReadyToRun.T2) {
}
System.out.print(letter);
r = ReadyToRun.T1;
}
}, "T2");
t1.start();
t2.start();
}
}
6、Semaphore
public class SemaphoreDemo {
static Thread t1 = null, t2 = null;
private static Semaphore semaphore1 = new Semaphore(1);
private static Semaphore semaphore2 = new Semaphore(0);
public static void main(String[] args) {
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
t1 = new Thread(() -> {
try {
for (String num : nums) {
semaphore1.acquire();
System.out.print(num);
semaphore2.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1");
t2 = new Thread(() -> {
try {
for (String letter : letters) {
semaphore2.acquire();
System.out.print(letter);
semaphore1.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T2");
t1.start();
t2.start();
}
}
7、BlockingQueue
public class BlockingQueueDemo {
static BlockingQueue<String> queue1 = new ArrayBlockingQueue<>(1);
static BlockingQueue<String> queue2 = new ArrayBlockingQueue<>(1);
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
t1 = new Thread(() -> {
try {
for (String num : nums) {
System.out.print(num);
queue1.put("ok");
queue2.take();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1");
t2 = new Thread(() -> {
try {
for (String letter : letters) {
queue1.take();
System.out.print(letter);
queue2.put("ok");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T2");
t1.start();
t2.start();
}
}
8、TransferQueue
public class TransferQueueDemo {
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
String[] nums = new String[]{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
};
String[] letters = new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
TransferQueue<String> queue = new LinkedTransferQueue<>();
t1 = new Thread(() -> {
try {
for (String num : nums) {
queue.transfer(num);
System.out.print(queue.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1");
t2 = new Thread(() -> {
try {
for (String letter : letters) {
System.out.print(queue.take());
queue.transfer(letter);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T2");
t1.start();
t2.start();
}
}