实现目标
实现现有20个线程去执行各自的任务,但是同一时刻只能开启5个线程去执行任务,只有某一个执行完了才能继续开启下面的线程,相关代码如下所示。
实现思路:
使用中间变量CONTROLLER来控制当前线程的大小。如果创建线程那就向队列加一个值,如果执行完了就拿出来一个值,并唤醒其他线程,这时其他线程发现有一个走了就会争抢新出的这个名额,当一个线程抢到了,其他就会阻塞掉。
public class CaptureService {
private static final List<Thread> THREADS = new ArrayList<>();
private static final LinkedList<Integer> CONTROLLER = new LinkedList<>();
private static final int MAX = 5;
public static void main(String[] args) {
IntStream.rangeClosed(0,20).forEach(i -> {
Thread thread = createThread("M" + i);
THREADS.add(thread);
thread.start();
});
//等待所有都执行完才会退出
THREADS.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("every task is done!!!");
}
private static Thread createThread(String name){
return new Thread(name){
@Override
public void run() {
synchronized (CONTROLLER){
while(CONTROLLER.size() >= MAX){
try {
Optional.of("当前线程已经最大了,不会继续创建 "+ CONTROLLER.size())
.ifPresent(System.out::println);
CONTROLLER.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//避免了线程安全问题
CONTROLLER.addLast(1);
}
//可以写在synchronized外层,因为不会出现线程安全,可以并发执行
try {
Optional.of(getName() + " is running task!").ifPresent(System.out::println);
Thread.sleep(3_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒其他线程争抢锁
synchronized (CONTROLLER){
//避免线程安全问题
CONTROLLER.removeFirst();
CONTROLLER.notifyAll();
Optional.of(getName() + " is done!").ifPresent(System.out::println);
}
}
};
}
}