后端笔试题-多线程JUC相关

发布于:2025-09-03 ⋅ 阅读:(22) ⋅ 点赞:(0)

JUC题

两个线程A和B,A线程打印1,3,5,7,9 B线程打印2,4,6,8,10,两个线程同时运行,要求打印结果为1,2,3,4,5,6.

本题主要考察线程的通信以及多线程的知识

public class AlternatingPrint {
    private static final Object lock = new Object();
    private static int currentNumber = 1; // 当前需要打印的数字
    private static final int MAX_NUMBER = 99; // 最大打印数字

    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            while (currentNumber <= MAX_NUMBER) {
                synchronized (lock) {
                    while (currentNumber % 2 == 0) { // 如果当前数字是偶数,等待
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Thread A prints: " + currentNumber);
                    currentNumber++;
                    lock.notify(); // 唤醒另一个线程
                }
            }
        });

        Thread threadB = new Thread(() -> {
            while (currentNumber <= MAX_NUMBER) {
                synchronized (lock) {
                    while (currentNumber % 2 != 0) { // 如果当前数字是奇数,等待
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Thread B prints: " + currentNumber);
                    currentNumber++;
                    lock.notify(); // 唤醒另一个线程
                }
            }
        });

        threadA.start();
        threadB.start();
    }

a打印完后就加1,进入等待状态,让b醒来进行打印,b打印完进入等待,唤醒a进行打印,交替操作实现

package threadDemo;

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

/**
 * @Author 泽
 * @Date 2025/2/28 13:50
 * 写两个线程A和B,A线程打印1,3,5,7,9 B线程打印2,4,6,8,10
 * 两个线程同时运行,要求打印结果为1,2,3,4,5,6.。。。。。
 */
public class AlternatingPrint {
    private static final ReentrantLock lock = new ReentrantLock();
    private static final Condition oddCondition = lock.newCondition();
    private static final Condition evenCondition = lock.newCondition();
    private static int currentNumber = 1; // 当前需要打印的数字
    private static final int MAX_NUMBER = 99; // 最大打印数字

    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    // 打印奇数并唤醒偶数线程
                    if (currentNumber <= MAX_NUMBER && currentNumber % 2 == 1) {
                        System.out.println("Thread A prints: " + currentNumber);
                        currentNumber++;
                        evenCondition.signal(); // 唤醒偶数线程
                    } else if (currentNumber > MAX_NUMBER) {
                        evenCondition.signal(); // 唤醒偶数线程使其退出
                        break;
                    } else {
                        oddCondition.await(); // 等待奇数打印机会
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                } finally {
                    lock.unlock();
                }
            }
        });

        Thread threadB = new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    // 打印偶数并唤醒奇数线程
                    if (currentNumber <= MAX_NUMBER && currentNumber % 2 == 0) {
                        System.out.println("Thread B prints: " + currentNumber);
                        currentNumber++;
                        oddCondition.signal(); // 唤醒奇数线程
                    } else if (currentNumber > MAX_NUMBER) {
                        oddCondition.signal(); // 唤醒奇数线程使其退出
                        break;
                    } else {
                        evenCondition.await(); // 等待偶数打印机会
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                } finally {
                    lock.unlock();
                }
            }
        });

        threadA.start();
        threadB.start();
    }
}

ReentranLock的Candition实现精确的线程唤醒,避免了synchronized的随机唤醒问题,并且增加线程中断的处理等

计算1-10000之间有多少个素数,越快越好

package threadDemo;

public class PrimeCalculator {
    private static final int START = 1; // 素数范围的起始值
    private static final int END = 100000; // 素数范围的结束值
    private static final int NUM_THREADS = 8; // 线程数量

    public static void main(String[] args) {
        System.out.println("Number of available processors: " + NUM_THREADS);
        System.out.println("Calculating prime numbers between " + START + " and " + END);

        long startTime = System.currentTimeMillis();

        // 将范围平均分配给每个线程
        int rangePerThread = (END - START) / NUM_THREADS;
        Thread[] threads = new Thread[NUM_THREADS];
        PrimeCounter[] counters = new PrimeCounter[NUM_THREADS];

        for (int i = 0; i < NUM_THREADS; i++) {
            int startRange = START + i * rangePerThread;
            int endRange = (i == NUM_THREADS - 1) ? END : startRange + rangePerThread;
            counters[i] = new PrimeCounter(startRange, endRange);
            threads[i] = new Thread(counters[i]);
            threads[i].start();
        }

        // 等待所有线程完成
        try {
            for (Thread thread : threads) {
                thread.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();
        System.out.println("Total time taken: " + (endTime - startTime) + " ms");

        // 统计所有线程的素数数量
        int totalPrimes = 0;
        for (PrimeCounter counter : counters) {
            totalPrimes += counter.getPrimeCount();
        }

        System.out.println("Total prime numbers found: " + totalPrimes);
    }
}

// 素数计数器类
class PrimeCounter implements Runnable {
    private final int start;
    private final int end;
    private int primeCount;

    public PrimeCounter(int start, int end) {
        this.start = start;
        this.end = end;
        this.primeCount = 0;
    }

    @Override
    public void run() {
        for (int num = start; num <= end; num++) {
            if (isPrime(num)) {
                primeCount++;
            }
        }
        System.out.println("Thread " + Thread.currentThread().getName() + " found " + primeCount + " primes in range [" + start + ", " + end + "]");
    }

    public int getPrimeCount() {
        return primeCount;
    }

    // 判断一个数是否为素数
    private boolean isPrime(int num) {
        if (num <= 1) return false;
        if (num == 2) return true;
        if (num % 2 == 0) return false;
        for (int i = 3; i <= Math.sqrt(num); i += 2) {
            if (num % i == 0) return false;
        }
        return true;
    }
}
  • PrimeCalculator类首先定义了三个核心常量:素数范围的起始值START(1)、结束值END(100000),以及线程数量NUM_THREADS(8)。
  • 根据线程数量来划分每个线程要判断的数据,明确每个线程的工作,并且定义计数器类继承Runnable接口实现基数
  • 主线程通过thread.join()等待所有子线程执行完毕,确保所有素数统计完成后再汇总结果:

遍历所有PrimeCounter实例,累加每个线程的素数计数得到totalPrimes

计算并输出总耗时(endTime - startTime)和总素数数量

通过“参数配置→任务拆分→并行计算→结果汇总”四步,实现了素数查找任务的多线程并行加速。


网站公告

今日签到

点亮在社区的每一天
去签到