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