来看题:
通过N个线程顺序循环打印从0至100,如给定N=3则输出:
thread0: 0
thread1: 1
thread2: 2
thread0: 3
thread1: 4
.....
1.审题
人家要的是什么呢?
2.解题
我该如何实现呢?
(想一想 不要着急往下看)
3.答案千千万,以下是个人的实现,仅供参考。。。调了一下午。。。(菜是原罪)
以下代码使用可重入锁ReentrantLock以及Condition实现。
public class QueuedJob {
//工作线程数量
static final int WORKER_COUNT = 3;
//是计数器鸭
static AtomicInteger countIndex = new AtomicInteger(0);
public static void main(String[] args){
//可重入锁 此处使用默认非公平锁即可
final ReentrantLock reentrantLock = new ReentrantLock();
final List<Condition> conditions = new ArrayList<>();
for(int i=0; i< WORKER_COUNT; i++){
//给每个工人分配一个用于通知干活的令牌 没喊你的时候都等着 喊你时再干
Condition condition = reentrantLock.newCondition();
conditions.add(condition);
//创建工人 i是工人序号 锁是保证同时只有一人在操作间 令牌主要用来通知下一位工人
Worker worker = new Worker(i, reentrantLock, conditions);
worker.start();
}
//等待1000毫秒 保证所有工人都进入等待状态
try {
Thread.sleep(1000);
}catch (Exception e){
}
//部分IDE不能在主线程 上锁喔 所以起新线程通知大家开工了
new Thread(new Runnable() {
@Override
public void run() {
reentrantLock.lock();
//Condition的 通知方法必须在持有锁时才可调用
//通知第一位工人开始动手啦
conditions.get(0).signal();
reentrantLock.unlock();
}
}).start();
}
static class Worker extends Thread{
//工人的序号
int index = 0;
ReentrantLock lock = null;
//记录所有工人的令牌
List<Condition> conditions = null;
public Worker(int index, ReentrantLock lock, List<Condition> conditions){
super("Worker:"+index);
this.index = index;
this.lock = lock;
this.conditions = conditions;
}
/**
* 当前工人工作结束时用来通知下一个工人
*/
private void signalNext(){
int nextIndex = ((index+1) == conditions.size())?0:(index +1);
//signal喊到对应的工人时 代码会从 await后继续执行
conditions.get(nextIndex).signal();
}
@Override
public void run(){
//上班喽 不数完100个数不能 下班喔
while(true) {
//锁住 保证操作间同时只有一位工人
lock.lock();
try {
System.out.println(this.getName() + " wait");
//进入工作准备状态 等待喊号 直到收到signal(喊号)时代码才会继续执行
conditions.get(index).await();
//等
//等
//等
//suddenly suddenly 收到喊号 开始工作啦
System.out.println(this.getName() + " continue");
//先看看当前工作进度
final int currentIndex = countIndex.get();
if (currentIndex > 100) {
//全部工作已经完成 下班啦!!! 记得告诉后面一位兄弟喔
signalNext();
System.out.println(this.getName() + " exit");
//退出循环 线程运行结束 下班
return;
}
//核心工作 打印数字
System.out.println((this.getName() + " " + currentIndex));
//计数器+1
countIndex.compareAndSet(currentIndex, currentIndex+1);
}catch (Exception e){
e.printStackTrace();
}finally {
//自己的任务完成 通知下一位干活
signalNext();
lock.unlock();
}
}
}
}
}
网友评论