后端笔试题-多线程JUC相关
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;}@Overridepublic 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)和总素数数量
通过“参数配置→任务拆分→并行计算→结果汇总”四步,实现了素数查找任务的多线程并行加速。