如定义一个字符数组为“1234567”,另一个字符数组为“abcdefg”,要求交替输出两个数组中的元素,如输出“1a2b3c4d5e6f7g”。
解法一:
使用LockSuport工具
LockSupport是一个线程工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,也可以在任意位置唤醒。
它的内部其实两类主要的方法:park(停车阻塞线程)和unpark(启动唤醒线程)。
package Thread;
import java.util.concurrent.locks.LockSupport;
public class Exchangeprinting {
static Thread t1,t2;
public static void main(String[] args) {
char[] c1="1234567".toCharArray();
char[] c2="abcdefg".toCharArray();
t1= new Thread(()->{
for (char a:c1){
System.out.print(a);
LockSupport.unpark(t2);
LockSupport.park();
}
});
t2=new Thread(()->{
for (char a:c2){
LockSupport.park();
LockSupport.unpark(t1);
System.out.print(a);
}
});
t2.start();
t1.start();
}
}
解法二:
ReentrantLock锁,用Condition作为信号量
- ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。
- ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。
- ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
package Thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class reentrantLock {
public static void main(String[] args) {
char[] a="123456789".toCharArray();
char[] b="abcdefghi".toCharArray();
Lock lock=new ReentrantLock();
Condition condition1=lock.newCondition();
Condition condition2=lock.newCondition();
new Thread(()->{
lock.lock();
for (char a1:a){
System.out.print(a1);
try {
condition2.signal();
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
condition2.signal();
}
}
lock.unlock();
}).start();
new Thread(()->{
lock.lock();
for (char a1 : b) {
System.out.print(a1);
try {
condition1.signal();
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
condition1.signal();
}
}
lock.unlock();
}).start();
}
}
解法三:
使用Transfer Queue队列,该类是JUC原子包中的类。
package Thread;
import java.util.concurrent.LinkedTransferQueue;
public class TransferQueue {
static Thread t1,t2;
public static void main(String[] args) {
char[] c1="1234567".toCharArray();
char[] c2="abcdefg".toCharArray();
LinkedTransferQueue<Character> transferQueue= new LinkedTransferQueue<>();
t1= new Thread(()->{
for (char a:c1){
try {
transferQueue.transfer(a);
System.out.print(transferQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2=new Thread(()->{
for (char a:c2){
try {
System.out.print(transferQueue.take());
transferQueue.transfer(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
t1.start();
}
}
解法四:
Synchronized+wait+notify,这种是最常用的办法。
package Thread;
public class WaitNotify {
public static void main(String[] args) {
char[] a="123456789".toCharArray();
char[] b="abcdefghi".toCharArray();
Object o=new Object();
new Thread(()->{
synchronized (o){
for (char a1:a){
System.out.print(a1);
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}).start();
new Thread(()->{
synchronized (o) {
for (char a1 : b) {
System.out.print(a1);
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}).start();
}
}