【面试手撕】非常规算法,多线程常见手撕题目

news2025/3/19 3:27:43

【面试手撕】非常规算法,多线程常见手撕题目

  • 生产者消费者
    • ReentrantLock实现的生产苹果/消费苹果
    • synchronized实现的生产消费
    • LinkedBlockingQueue阻塞队列方法实现
    • 多条件资源分配
    • 分布式任务调度模拟
  • 交替打印
    • 两个线程交替打印1-100之间的数
      • ReentrantLock 实现
      • synchronized实现
      • Semaphore实现
    • 三个线程交替打印1-100之间的数
      • ReentrantLock
      • Synchronized
      • Semaphore
  • 线程池
    • 手写线程池
    • 使用线程池实现任务
      • **机场安检模拟(现实场景)**

生产者消费者

ReentrantLock实现的生产苹果/消费苹果

仓库类:

  • 定义最大苹果数量+当前苹果数量
  • 生产/消费方法

无非是,先判断条件是否满足,不满足就调用await等待,满足的话生产/消费苹果,之后调用signal唤醒其他线程。

注意用的是条件变量,full,empty

生产的时候,仓库满了调用full.await()等待,生产后,调用empty.signal()唤醒消费者。消费是时候相反即可。

最后,注意try,catch,finally 在finally中实现解锁。

package Others.JUC;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumerDemo1 {

    public static void main(String[] args) {
        // 1.初始化3个生产者线程
        Storage storage = new Storage();
        for(int i = 0;i<3;i++){
            new Thread(new Producer(storage),"生产者"+i).start();
        }
        // 2.初始化2个消费者线程
        for(int i = 0;i<2;i++){
            new Thread(new Consumer(storage),"消费者"+i).start();
        }
    }
}

class Storage{
    private int capacity = 10 ;// 最多容纳10个苹果
    private int count = 0; // 当前苹果数量
    private ReentrantLock lock = new ReentrantLock();
    private Condition full = lock.newCondition();
    private Condition empty = lock.newCondition();

    public void produce() throws InterruptedException {
        try{
            lock.lock();
            // 生产苹果
            while(count>=capacity){
                full.await();
            }
            count++;
            System.out.println(Thread.currentThread().getName()+" 生产了一个苹果,当前苹果数量:"+count);
            empty.signal();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        TimeUnit.SECONDS.sleep(1); // 模拟生产苹果的时间
    }

    public void consume() throws InterruptedException {
        try{
            lock.lock();
            // 条件不满足,等待
            while(count<=0){
                empty.await();
            }
            count--;
            System.out.println(Thread.currentThread().getName()+" 消费了一个苹果,当前苹果数量:"+count);
            full.signal();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        TimeUnit.SECONDS.sleep(1); // 模拟消费苹果的时间
    }
}

class Producer implements Runnable{
    private Storage storage;
    public Producer(Storage storage){
        this.storage = storage;
    }

    public Producer(){}

    @Override
    public void run() {
        while(true){
            try{
                Thread.sleep(1000); // 模拟生产苹果的时间,1秒生产一个苹果
                storage.produce();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}


class Consumer implements Runnable{
    private Storage storage;
    public Consumer(Storage storage){
        this.storage = storage;
    }

    public Consumer(){}

    @Override
    public void run() {
        while(true){
            try{
                Thread.sleep(1000); // 模拟消费苹果的时间,1秒消费一个苹果
                storage.consume();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }

    }
}

synchronized实现的生产消费

核心是用synchronized锁住了,由于synchronized可以锁随便一个Object,所以把缓冲区buffer作为synchronized锁住的对象即可。

这里主要的区别就是Storage的实现不一致。其他的一致。

class Storage{
    // 缓冲区
    private LinkedList<Object> buffer = new LinkedList<>();
    // 缓冲区大小
    private final int MAX_SIZE = 10;

    public void produce(){
        synchronized(buffer){
            while(buffer.size()+1>MAX_SIZE){
                System.out.println("缓冲区已满,生产者等待");
                try{
                    buffer.wait();
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
            buffer.add(new Object());
            System.out.println("生产者生产一个产品,当前缓冲区大小为"+buffer.size());
            buffer.notify();
        }
    }

    public void consume(){
        synchronized(buffer){
            while(buffer.size()==0){
                System.out.println("缓冲区为空,消费者等待");
                try{
                    buffer.wait();
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
            buffer.remove();
            System.out.println("消费者消费一个产品,当前缓冲区大小为"+buffer.size());
            buffer.notify();
        }
    }
}


class Producer implements Runnable{
    private Storage storage;
    public Producer(Storage storage){
        this.storage = storage;
    }

    public Producer(){}

    @Override
    public void run() {
        while(true){
            try{
                Thread.sleep(1000); // 模拟生产苹果的时间,1秒生产一个苹果
                storage.produce();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

LinkedBlockingQueue阻塞队列方法实现

这里更简单了,不需要手动加锁。只需要使用put/take方法,会自己阻塞

class Storage{
    LinkedBlockingQueue<Object> buffer = new LinkedBlockingQueue<>(10);

    public void produce(){
        try{
            buffer.put(new Object());
            System.out.println(Thread.currentThread().getName()+" 生产了一个苹果,当前苹果数量:"+buffer.size());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void consume(){
        try{
            buffer.take();
            System.out.println(Thread.currentThread().getName()+" 消费了一个苹果,当前苹果数量:"+buffer.size());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

多条件资源分配

场景: 某工厂需要组装产品,要求:

  • 零件A和零件B必须同时存在才能组装
  • 仓库最多存放5个A和5个B
  • 2个供应商线程分别生产A/B(随机0.5~1秒生产1个)
  • 3个组装线程消耗1A+1B组合(每次组装耗时1秒)

要求: 使用 wait/notifyAll 实现资源协调,避免死锁

public class FactoryAssembly {
    private int partA = 0;
    private int partB = 0;
    private final int MAX_PARTS = 5;
    private int assembledProducts = 0;

    public static void main(String[] args) {
        FactoryAssembly factory = new FactoryAssembly();
        
        // 创建供应商线程A
        Thread supplierA = new Thread(() -> {
            try {
                while (true) {
                    factory.producePartA();
                    // 随机生产时间 0.5-1秒
                    Thread.sleep(500 + (long)(Math.random() * 500));
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 创建供应商线程B
        Thread supplierB = new Thread(() -> {
            try {
                while (true) {
                    factory.producePartB();
                    // 随机生产时间 0.5-1秒
                    Thread.sleep(500 + (long)(Math.random() * 500));
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 创建3个组装线程
        for (int i = 1; i <= 3; i++) {
            final int assemblyLineId = i;
            Thread assemblyLine = new Thread(() -> {
                try {
                    while (true) {
                        factory.assembleParts(assemblyLineId);
                        // 组装时间1秒
                        Thread.sleep(1000);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
            assemblyLine.start();
        }
        
        supplierA.start();
        supplierB.start();
    }
    
    // 生产零件A
    public synchronized void producePartA() throws InterruptedException {
        // 如果A零件已达到上限,等待
        while (partA >= MAX_PARTS) {
            System.out.println("零件A仓库已满,供应商A等待中...");
            wait();
        }
        
        partA++;
        System.out.println("供应商A生产了一个零件A,当前库存: A=" + partA + ", B=" + partB);
        // 通知所有等待的线程
        notifyAll();
    }
    
    // 生产零件B
    public synchronized void producePartB() throws InterruptedException {
        // 如果B零件已达到上限,等待
        while (partB >= MAX_PARTS) {
            System.out.println("零件B仓库已满,供应商B等待中...");
            wait();
        }
        
        partB++;
        System.out.println("供应商B生产了一个零件B,当前库存: A=" + partA + ", B=" + partB);
        // 通知所有等待的线程
        notifyAll();
    }
    
    // 组装产品
    public synchronized void assembleParts(int lineId) throws InterruptedException {
        // 如果A或B零件不足,等待
        while (partA < 1 || partB < 1) {
            System.out.println("组装线 #" + lineId + " 等待零件,当前库存: A=" + partA + ", B=" + partB);
            wait();
        }
        
        // 消耗零件A和B各一个
        partA--;
        partB--;
        assembledProducts++;
        
        System.out.println("组装线 #" + lineId + " 完成一个产品组装! 总计: " + assembledProducts + 
                ",剩余库存: A=" + partA + ", B=" + partB);
        
        // 通知所有等待的线程
        notifyAll();
    }
}

分布式任务调度模拟

题目5:分布式任务调度模拟(综合)

需求

  • 主节点(Producer)每隔1秒生成一个带优先级的任务
  • 3个工作节点(Consumer)从任务队列获取任务执行
  • 高优先级任务(如优先级>5)必须立即抢占执行
  • 使用 PriorityBlockingQueue 实现任务队列
  • 任务执行时间随机(1~3秒)
import java.util.concurrent.*;

public class DistributedTaskScheduler {
    // 定义任务类
    static class Task implements Comparable<Task> {
        private final int id;
        private final int priority;
        private final int executionTime;
        
        public Task(int id, int priority) {
            this.id = id;
            this.priority = priority;
            // 随机执行时间 1-3秒
            this.executionTime = 1000 + (int)(Math.random() * 2000);
        }
        
        public int getId() {
            return id;
        }
        
        public int getPriority() {
            return priority;
        }
        
        public int getExecutionTime() {
            return executionTime;
        }
        
        // 优先级比较,高优先级的任务排在前面
        @Override
        public int compareTo(Task other) {
            return other.priority - this.priority;
        }
        
        @Override
        public String toString() {
            return "Task #" + id + " (优先级: " + priority + ")";
        }
    }
    
    public static void main(String[] args) {
        // 使用优先级队列存储任务
        PriorityBlockingQueue<Task> taskQueue = new PriorityBlockingQueue<>();
        
        // 创建锁对象用于高优先级任务抢占
        Object preemptionLock = new Object();
        
        // 任务计数器
        final int[] taskCounter = {0};
        
        // 主节点线程生成任务
        Thread producer = new Thread(() -> {
            try {
                while (true) {
                    // 生成随机优先级 (1-10)
                    int priority = 1 + (int)(Math.random() * 10);
                    Task task = new Task(++taskCounter[0], priority);
                    taskQueue.put(task);
                    
                    System.out.println("主节点生成: " + task);
                    
                    // 如果是高优先级任务,通知工作节点抢占
                    if (priority > 5) {
                        System.out.println("!!!! 高优先级任务 #" + task.getId() + " (优先级: " + priority + ") 需要抢占执行!");
                        synchronized (preemptionLock) {
                            preemptionLock.notifyAll();
                        }
                    }
                    
                    // 每隔1秒生成一个任务
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 创建3个工作节点线程
        for (int i = 1; i <= 3; i++) {
            final int workerId = i;
            Thread consumer = new Thread(() -> {
                try {
                    while (true) {
                        // 从队列获取任务
                        Task task = taskQueue.take();
                        
                        System.out.println("工作节点 #" + workerId + " 开始执行: " + task);
                        
                        // 模拟任务执行
                        Thread.sleep(task.getExecutionTime());
                        
                        System.out.println("工作节点 #" + workerId + " 完成任务: " + task);
                        
                        // 检查是否有高优先级任务需要执行
                        if (!taskQueue.isEmpty() && taskQueue.peek().getPriority() > 5) {
                            System.out.println("工作节点 #" + workerId + " 发现高优先级任务,立即处理!");
                        } else {
                            // 如果没有高优先级任务,稍微休息一下
                            synchronized (preemptionLock) {
                                try {
                                    preemptionLock.wait(500);
                                } catch (InterruptedException e) {
                                    Thread.currentThread().interrupt();
                                }
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
            consumer.start();
        }
        
        producer.start();
    }
}

交替打印

两个线程交替打印1-100之间的数

ReentrantLock 实现

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TwoThreadsReentrantLock {
    private static volatile int num = 1;
    private static final int MAX = 100;
    private static Lock lock = new ReentrantLock();
    private static Condition cA = lock.newCondition();
    private static Condition cB = lock.newCondition();

    public static void main(String[] args) {
        new Thread(()->{
            while(num<MAX){
                try{
                    lock.lock();
                    while(num%2==0){
                        cA.await();
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    cB.signal();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        },"线程A").start();
        new Thread(()->{
            while(num<MAX){
                try{
                    lock.lock();
                    while(num%2!=0){
                        cB.await();
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    cA.signal();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        },"线程B").start();
    }
}

synchronized实现

public class TwoThreadsSynchronized {
    private static volatile int num = 1;
    private static final int MAX = 100;
    private static final Object lock = new Object();

    public static void main(String[] args) {
        new Thread(()->{
            while(num<MAX){
                synchronized(lock){
                    while(num%2==0){
                        try{
                            lock.wait();
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    lock.notify();
                }
            }
        },"t1").start();

        new Thread(()->{
            while(num<MAX){
                synchronized(lock){
                    while(num%2==1){
                        try{
                            lock.wait();
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    lock.notify();
                }
            }
        },"t2").start();
    }
}

Semaphore实现

import java.util.concurrent.Semaphore;

public class TwoThreadsSemaphore {
    private static volatile int num = 1;
    private static final int MAX = 100;
    private static Semaphore s1 = new Semaphore(1);
    private static Semaphore s2 = new Semaphore(0);

    public static void main(String[] args) {
        new Thread(()->{
            while(num<MAX){
                try{
                    s1.acquire();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+" "+num++);
                s2.release();
            }
        },"t1").start();

        new Thread(()->{
            while(num<MAX){
                try{
                    s2.acquire();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+" "+num++);
                s1.release();
            }
        },"t2").start();
    }
}

三个线程交替打印1-100之间的数

ReentrantLock

public class ThreeThreadReentrantLock {
    static class PrintTask{
        private static volatile int num = 1;
        private static final int MAX = 100;
        private static Lock lock = new ReentrantLock();
        private static Condition cA = lock.newCondition();
        private static Condition cB = lock.newCondition();
        private static Condition cC = lock.newCondition();

        public void print1(){
            while(num<=MAX){
                try{
                    lock.lock();
                    while(num%3!=1){
                        cA.await();
                    }
                    if(num>MAX){
                        break;
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    cB.signal();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                finally {
                    lock.unlock();
                }
            }
        }

        public void print2(){
            while(num<=MAX){
                try{
                    lock.lock();
                    while(num%3!=2){
                        cB.await();
                    }
                    if(num>MAX){
                        break;
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    cC.signal();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }

        public void print3(){
            while(num<=MAX){
                try{
                    lock.lock();
                    while(num%3!=0){
                        cC.await();
                    }
                    if(num>MAX){
                        break;
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    cA.signal();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }

        }
    }

    public static void main(String[] args) {
        PrintTask task = new PrintTask();
        new Thread(task::print1,"线程A").start();
        new Thread(task::print2,"线程B").start();
        new Thread(task::print3,"线程C").start();
    }
}

Synchronized

public class ThreeThreadSynchronized {
    static class PrintTask{
        private static volatile int num = 1;
        private static final int MAX = 100;
        private static final Object lock = new Object();
        private boolean isA = true;
        private boolean isB = false;
        private boolean isC = false;
        public void print1(){
            while(num<=MAX){
                synchronized(lock){
                while(!isA){
                    try{
                        lock.wait();
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
                if(num>MAX){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+" "+num++);
                    isA = false;
                    isB = true;
                    lock.notifyAll();
                }
            }
        }

        public void print2(){
            while(num<=MAX){
            synchronized(lock){
                while(!isB){
                try{
                    lock.wait();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                }
                if(num>MAX){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+" "+num++);
                isB = false;
                isC = true;
                lock.notifyAll();
            }
            }
        }


        public void print3(){
            while(num<=MAX){

                synchronized(lock){
                    while(!isC){
                        try{
                            lock.wait();
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }

                    }
                    if(num>MAX){
                        break;
                    }
                    System.out.println(Thread.currentThread().getName()+" "+num++);
                    isC = false;
                    isA = true;
                    lock.notifyAll();
                }
            }
        }
    }

    public static void main(String[] args) {
        PrintTask task = new PrintTask();
        new Thread(task::print1,"线程A").start();
        new Thread(task::print2,"线程B").start();
        new Thread(task::print3,"线程C").start();

    }
}

Semaphore

import java.util.concurrent.Semaphore;

public class ThreeThreadSemaphore {

    static class PrintTask{
        private static volatile int num = 1;
        private static final int MAX = 100;
        private static Semaphore s1 = new Semaphore(1);
        private static Semaphore s2 = new Semaphore(0);
        private static Semaphore s3 = new Semaphore(0);

        public void print1(){

            while(num<=MAX){
                try{
                    s1.acquire();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                if(num>MAX){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+" "+num++);
                s2.release();
            }
        }

        public void print2(){
            while(num<=MAX){
                try{
                    s2.acquire();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                if(num>MAX){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+" "+num++);
                s3.release();
            }
        }

        public void print3(){
            while(num<=MAX){
                try{
                    s3.acquire();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                if(num>MAX){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+" "+num++);
                s1.release();
            }
        }
    }



    public static void main(String[] args) {
        PrintTask task = new PrintTask();
        new Thread(task::print1,"t1").start();
        new Thread(task::print2,"t2").start();
        new Thread(task::print3,"t3").start();
    }


}

线程池

手写线程池

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class CustomThreadPool {
    private final BlockingQueue<Runnable> taskQueue;
    private final List<WorkerThread> workers;
    private final AtomicBoolean isShutdown;
    private final int corePoolSize;
    private final AtomicInteger threadCount;

    public CustomThreadPool(int corePoolSize) {
        this.corePoolSize = corePoolSize;
        this.taskQueue = new LinkedBlockingQueue<>();
        this.workers = new ArrayList<>(corePoolSize);
        this.isShutdown = new AtomicBoolean(false);
        this.threadCount = new AtomicInteger(0);
        
        // 初始化线程池中的工作线程
        for (int i = 0; i < corePoolSize; i++) {
            WorkerThread worker = new WorkerThread("Worker-" + i);
            workers.add(worker);
            worker.start();
        }
    }
    
    // 提交任务到线程池
    public void execute(Runnable task) {
        if (isShutdown.get()) {
            throw new IllegalStateException("线程池已关闭,无法接受新任务");
        }
        
        try {
            taskQueue.put(task);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    // 关闭线程池
    public void shutdown() {
        isShutdown.set(true);
        
        // 中断所有工作线程
        for (WorkerThread worker : workers) {
            if (!worker.isInterrupted()) {
                worker.interrupt();
            }
        }
    }
    
    // 等待所有任务完成
    public void awaitTermination() throws InterruptedException {
        for (WorkerThread worker : workers) {
            worker.join();
        }
    }
    
    // 获取当前队列中等待的任务数
    public int getQueueSize() {
        return taskQueue.size();
    }
    
    // 获取活跃线程数
    public int getActiveThreadCount() {
        return threadCount.get();
    }
    
    // 工作线程类
    private class WorkerThread extends Thread {
        public WorkerThread(String name) {
            super(name);
        }
        
        @Override
        public void run() {
            while (!isShutdown.get() || !taskQueue.isEmpty()) {
                try {
                    // 从队列中获取任务
                    Runnable task = taskQueue.poll();
                    
                    if (task != null) {
                        threadCount.incrementAndGet();
                        try {
                            System.out.println(Thread.currentThread().getName() + " 开始执行任务");
                            task.run();
                            System.out.println(Thread.currentThread().getName() + " 完成任务");
                        } finally {
                            threadCount.decrementAndGet();
                        }
                    } else {
                        // 如果队列为空,等待新任务
                        Thread.sleep(100);
                    }
                } catch (InterruptedException e) {
                    // 线程被中断,结束循环
                    break;
                } catch (Exception e) {
                    // 任务执行中的异常不应该影响工作线程
                    System.err.println(Thread.currentThread().getName() + " 执行任务时发生异常: " + e.getMessage());
                }
            }
            
            System.out.println(Thread.currentThread().getName() + " 退出");
        }
    }
    
    // 测试自定义线程池
    public static void main(String[] args) throws InterruptedException {
        // 创建一个有3个线程的线程池
        CustomThreadPool threadPool = new CustomThreadPool(3);
        
        // 提交10个任务
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            threadPool.execute(() -> {
                try {
                    System.out.println("执行任务 #" + taskId);
                    // 模拟任务执行时间
                    Thread.sleep(1000);
                    System.out.println("任务 #" + taskId + " 执行完成");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        // 等待5秒后关闭线程池
        Thread.sleep(5000);
        System.out.println("关闭线程池");
        threadPool.shutdown();
        
        // 等待所有任务完成
        threadPool.awaitTermination();
        System.out.println("所有任务已完成,程序退出");
    }
}

使用线程池实现任务

机场安检模拟(现实场景)

场景

  • 3个安检口(线程)同时工作
  • 旅客(任务)以随机间隔(0~2秒)到达,加入队列
  • 每个安检需要2秒处理时间
  • 使用 ExecutorService 线程池实现

扩展要求

  • 显示实时排队人数
  • 当排队超过10人时增加1个临时安检口
  • 使用 ThreadPoolExecutor 动态调整
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SecurityCheckSimulation {
    // 旅客计数器
    private static final AtomicInteger passengerCount = new AtomicInteger(0);
    // 队列中等待的旅客数量
    private static final AtomicInteger waitingCount = new AtomicInteger(0);
    // 安检口初始数量
    private static int initialCheckpoints = 3;
    // 安检口最大数量
    private static int maxCheckpoints = 4;

    public static void main(String[] args) {
        // 创建可调整大小的线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                initialCheckpoints, // 核心线程数
                maxCheckpoints, // 最大线程数
                60L,TimeUnit.SECONDS, // 线程空闲时间
                new LinkedBlockingQueue<>(), // 任务队列
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );

        // 模拟旅客到达
        Thread passengerGenerator = new Thread(()->{
            try{
                while(true){
                    // 新旅客到达
                    int passengerId = passengerCount.incrementAndGet();
                    waitingCount.incrementAndGet();
                    System.out.println("Passenger " + passengerId + " 到达安检。当前排队人数:"+waitingCount.get());
                    // 动态调整安检口数量
                    if(waitingCount.get()>10 && executor.getCorePoolSize()<maxCheckpoints){
                        executor.setCorePoolSize(maxCheckpoints);
                        System.out.println("===== 排队人数过多,增加临时安检口! 当前安检口: "+executor.getCorePoolSize()+"=====");
                    }

                    // 将旅客提交给安检口
                    executor.submit(()->processPassenger(passengerId));

                    // 模拟旅客到达的随机时间间隔,随机等待0-2秒
                    Thread.sleep((long) (Math.random()*2000));
                }
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        });

        passengerGenerator.start();
    }
    private static void processPassenger(int passengerId)  {
        // 模拟安检过程
        System.out.println("Passenger " + passengerId + " 正在安检...");
        // 安检耗时2秒
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Passenger " + passengerId + " 安检完成。");
        waitingCount.decrementAndGet();
        System.out.println("当前排队人数:"+waitingCount.get());
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2317546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

批量给 Excel 添加或删除密码保护|Excel 批量设置打开密码和只读密码

我们在将 Excel 文档发送给第三方或者进行存档的时候&#xff0c;对 Excel 文档添加密码保护是非常重要的一个操作。添加保护后的 Excel 文档。就只能有相应权限的用户才能够打开或者编辑操作。尤其是当我们 Excel 文档中内容非常敏感非常重要的时候&#xff0c;添加保护就显得…

4.JVM-垃圾回收介绍

记录个人学习中记录笔记&#xff0c;如有错误请您指正&#xff0c;谢谢&#x1f64f; 垃圾回收器发展史 传统垃圾回收: 分代回收 不同代有不同的垃圾回收机制 保底 标记清除算法 垃圾识别算法 引用计数法 缺陷:下图2 出现循环引用 无法解决 可达性分析 大部分(Java,pytho…

Redis-锁-商品秒杀防止超卖

一、秒杀&#xff08;Seckill&#xff09;​ 1. ​定义 ​秒杀&#xff1a;短时间内&#xff08;如1秒内&#xff09;大量用户同时抢购 ​限量低价商品 的营销活动。​典型场景&#xff1a;双11热门商品抢购、小米手机首发、演唱会门票开售。 2. ​技术挑战 挑战点说明后果…

第一个vue项目

项目目录 启动vue项目 npm run serve 1.vue.config.js文件 (CLI通过vue-cli-serve启动项目&#xff0c;解析配置配置文件vue-condig-js&#xff09; // vue.config.js //引入path板块&#xff0c;这是Node.js的一个内置模块&#xff0c;用于处理文件路径&#xff0c;这里引用…

基于CNN的多种类蝴蝶图像分类

基于CNN的多种类蝴蝶图像分类&#x1f98b; 基于卷积神经网络对64992786张图像&#xff0c;75种不同类别的蝴蝶进行可视化分析、模型训练及分类展示 导入库 import pandas as pd import os import matplotlib.pyplot as plt import seaborn as sns import numpy as np from …

Unity插件-适用于画面传输的FMETP STREAM使用方法(三)基础使用

目录 一、插件介绍 二、组件介绍 三、Game View Streaming 1、使用 FM Network UDP 的基本设置 Server Scene Client Scene 2、使用使用 FM WebSocket 的基本设置 四、Audio Streaming 五、Microphone Streaming 一、插件介绍 ​​​​​​Unity插件-适用于画面传输的…

微信小程序wx.request接口报错(errno: 600001, errMsg: “request:fail -2:net::ERR_FAILED“)

来看看报错 报错如下: 请求发送部分,代码如下: uni.request({url: self.serverUrl "/getRealName",method: GET,data: {"code": self.info.code,},header: {"Authorization": uni.getStorageSync(tokenHead) uni.getStorageSync(token)}}…

基于Python+MySQL编写的(WinForm)图书管理系统

一、项目需求分析 1.1 项目介绍 项目背景 图书馆管理系统是一些单位不可缺少的部分,书籍是人类不可缺少的精神食粮&#xff0c;尤其对于学校来说&#xff0c;尤其重要。所以图书馆管理系统应该能够为用户提供充足的信息和快捷的查询手段。但一直以来人们使用传统人工的方式管…

[贪心算法] 摆动序列

1.解析 这里我们的贪心体现在&#xff0c;这里我们只需要找到每一个拐点位置的数字即可&#xff0c; 证明&#xff1a; 当我们在A点时&#xff0c;我们下一步的选择有四种 A到D这个线段内的数字&#xff08;不包括D&#xff09;选择D点D到F的点F之后的点 对于A到D来说&#xf…

WPF未来展望:紧跟技术发展趋势,探索新的可能性

WPF未来展望&#xff1a;紧跟技术发展趋势&#xff0c;探索新的可能性 一、前言二、WPF 与.NET 技术的融合发展2.1 拥抱.NET Core2.2 利用.NET 5 及后续版本的新特性 三、WPF 在新兴技术领域的应用拓展3.1 与云计算的结合3.2 融入物联网生态 四、WPF 在用户体验和设计方面的创新…

低空经济腾飞:无人机送货、空中通勤,未来已来

近年来&#xff0c;低空经济逐渐成为社会关注的焦点。从无人机送货到“空中的士”&#xff0c;再到飞行培训的火热进行&#xff0c;低空经济正迎来前所未有的发展机遇。随着技术进步和政策支持&#xff0c;这一曾经看似遥远的未来场景&#xff0c;正逐步变为现实。 低空经济如何…

QT编译器mingw与msvc区别及环境配置

一.QT编译器mingw与msvc主要区别 二.QT开发环境配置 1. MinGW 配置 安装步骤&#xff1a; 通过 Qt 官方安装器 安装时勾选 MinGW 组件&#xff08;如 Qt 6.7.0 MinGW 64-bit&#xff09;。 确保系统环境变量包含 MinGW 的 bin 目录&#xff08;如 C:\Qt\Tools\mingw1120_64…

【css酷炫效果】纯CSS实现进度条加载动画

【css酷炫效果】纯CSS实现进度条加载动画 缘创作背景html结构css样式完整代码基础版进阶版 效果图 通过CSS渐变与背景位移动画&#xff0c;无需JavaScript即可创建流体动态进度条。 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;https://download.csdn.net/download/u…

Feedback-Guided Autonomous Driving

Feedback-Guided Autonomous Driving idea 问题设定&#xff1a;基于 CARLA 的目标驱动导航任务&#xff0c;通过知识蒸馏&#xff0c;利用特权智能体的丰富监督信息训练学生传感器运动策略函数 基于 LLM 的端到端驱动模型&#xff1a;采用 LLaVA 架构并添加航点预测头&#…

图解AUTOSAR_CP_WatchdogDriver

AUTOSAR WatchdogDriver模块详解 AUTOSAR MCAL层看门狗驱动模块详细解析 目录 1. 模块概述2. 架构位置 2.1. 组件架构 3. 主要功能4. API接口5. 配置参数 5.1. 配置模型 6. 错误代码7. 状态管理 7.1. 状态机 8. 处理流程 8.1. 活动流程 9. 操作序列 9.1. 典型操作序列 10. 硬件…

大数据学习(65)- Hue详解

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…

C语言学习笔记(第三部份)

说明&#xff1a;由于所有内容放在一个md文件中会非常卡顿&#xff0c;本文件将接续C_1.md文件的第三部分 整型存储和大小端 引例&#xff1a; int main(void) {// printf("%d\n", SnAdda(2, 5));// PrintDaffodilNum(10000);// PrintRhombus(3);int i 0;int arr[…

深入理解蒸馏、Function Call、React、Prompt 与 Agent

AI基础概念与实操 一、什么是蒸馏二、如何理解Function Call、React、Prompt与Agent&#xff08;一&#xff09;Function Call与Agent&#xff08;二&#xff09;Agent中的React概念&#xff08;三&#xff09;Prompt与Agent的关联 实操演练function callprompt 一、什么是蒸馏…

记录一个SQL自动执行的html页面

在实际工作场景中&#xff0c;需要运用到大量SQL语句更新业务逻辑&#xff0c;对程序员本身&#xff0c;写好的sql语句执行没有多大问题&#xff08;图1&#xff09;&#xff0c;但是对于普通用户来说还是有操作难度的。因此我们需要构建一个HTML页面&#xff08;图2&#xff0…

qt介绍图表 charts 一

qt chartsj基于Q的Graphics View框架&#xff0c;其核心组件是QChartView和QChart.QChartView是一个显示图表的独立部件&#xff0c;基类为QGraphicsView.QChar类管理图表的序列&#xff0c;图例和轴示意图。 绘制一个cos和sin曲线图&#xff0c;效果如下 实现代码 #include…