在学习多线程中看到有个题目:使用2个线程打印多个26个字母,看了网上的答案 基本都是使用wait和notify方法,对这个答案不是很满意,虽然功能是实现了 ,但是在扩展性方面有些差,所以在网上找资料 自己尝试着写了一个扩展性相对于 wait和notify 扩展性强一些的方式,在实际开发工作中可能不会用到
参考文章:https://blog.csdn.net/weixin_41826973/article/details/105501187
代码如下:
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Function;
/***
* n个线程交替打印26个字母
*/
public class TestPrintAlphabet {
public static void main(String[] args) throws InterruptedException {
LinkedList<String> list = new LinkedList<>(Arrays.asList("abcdefghijklmnopqrstuvwxyz".split("")));
Function<T1, Boolean> isEnd = e -> list.size() > 0;
Consumer<Object> operation = e -> {
System.out.println(Thread.currentThread().getName() + " - " + list.removeFirst());
};
T1 t = new T1(operation, isEnd);
Thread t1 = new Thread(t),
t2 = new Thread(t),
t3 = new Thread(t);
t.initConditions(t1, t2, t3);
t.notifyFirstCodition();
}
}
class T1 implements Runnable {
private Lock lock = new ReentrantLock();
private Map<Thread, Integer> threadMap = new HashMap<>();
// 线程对应的锁队列
private List<Condition> conditions = new ArrayList<>();
// 队列索引
private volatile int conditionIndex = 1;
// 结束条件
private Function<T1, Boolean> isEnd;
// 执行的操作
private Consumer<Object> operation;
public T1(Consumer<Object> operation, Function<T1, Boolean> isEnd){
this.operation = operation;
this.isEnd = isEnd;
}
@Override
public void run() {
Condition nowCondition;
lock.lock();
while (isEnd.apply(this)) {
nowCondition = conditions.get(threadMap.get(Thread.currentThread()));
try {
nowCondition.await();
if(!isEnd.apply(this)){
// 执行结束,唤起所有等待线程,结束运行
notifyAllCondition();
break;
}
operation.accept(this);
notifyNextCondition();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.unlock();
}
/***
* 初始化线程列表
* @param threads
*/
public void initConditions(Thread... threads) {
if(threads != null){
Thread t;
for(int i = 0; i < threads.length;i++){
t = threads[i];
threadMap.put(t, i);
conditions.add(lock.newCondition());
t.start();
}
}
}
/***
* 唤醒第一个线程
* @throws InterruptedException
*/
public void notifyFirstCodition() throws InterruptedException {
// 延迟执行,防止t1线程还没有尝试获取锁,主线程就唤醒t1线程,由于t1线程还没有获取到锁 所以唤起t1线程是不会生效的,主线程唤醒未获取锁的的t1线程后 t1线程无法被唤起 导致死锁
Thread.sleep(1);
if(conditions.size() > 0){
lock.lock();
conditions.get(0).signal();
lock.unlock();
}
}
/***
* 唤醒下一个线程
*/
public void notifyNextCondition(){
if(conditionIndex >= conditions.size()){
conditionIndex = 0;
}
conditions.get(conditionIndex).signal();
conditionIndex++;
}
/***
* 唤醒所有线程
*/
public void notifyAllCondition(){
lock.lock();
for(Condition c : conditions){
c.signal();
}
lock.unlock();
}
}