一直学习理论怎么能不做练习呢?下面我将出几个编程题来巩固编程。
练习1:
新建三个线程,使用并发编程,同时计算三个线程的数并且输出计算的过程,线程1计算从1加到100,线程2计算50的阶乘,线程三计算根号三并且输出小数点后十位。
答案
import com.google.common.util.concurrent.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class MultiThreadCalculator {
// 创建监听线程池
private static final ListeningExecutorService executor =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(3));
public static void main(String[] args) {
// 启动三个计算任务
ListenableFuture<?> additionFuture = executor.submit(new AdditionTask());
ListenableFuture<?> multiplicationFuture = executor.submit(new MultiplicationTask());
ListenableFuture<?> sqrtFuture = executor.submit(new SquareRootTask());
// 添加回调处理异常
Futures.addCallback(additionFuture, new LoggingCallback(), executor);
Futures.addCallback(multiplicationFuture, new LoggingCallback(), executor);
Futures.addCallback(sqrtFuture, new LoggingCallback(), executor);
// 等待所有任务完成
ListenableFuture<?> allFutures = Futures.allAsList(
additionFuture, multiplicationFuture, sqrtFuture
);
try {
allFutures.get();
System.out.println("\n所有计算任务完成!");
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
// 加法任务:计算1加到100
static class AdditionTask implements Runnable {
@Override
public void run() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
System.out.println("[加法线程] 添加 " + i + " → 当前总和: " + sum);
Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
}
System.out.println("\n[加法线程] 最终结果: 1到100的和 = " + sum);
}
}
// 乘法任务:计算2乘到50(使用BigInteger避免溢出)
static class MultiplicationTask implements Runnable {
@Override
public void run() {
BigInteger product = BigInteger.ONE;
for (int i = 2; i <= 50; i++) {
product = product.multiply(BigInteger.valueOf(i));
System.out.println("[乘法线程] 乘以 " + i + " → 当前乘积: " + product);
Uninterruptibles.sleepUninterruptibly(70, TimeUnit.MILLISECONDS);
}
System.out.println("\n[乘法线程] 最终结果: 2到50的乘积 = " + product);
}
}
// 开方任务:计算√3的小数点后10位数字
static class SquareRootTask implements Runnable {
@Override
public void run() {
// 计算√3到小数点后20位精度
BigDecimal sqrt3 = BigDecimal.valueOf(3).sqrt(new MathContext(20));
String decimalPart = sqrt3.toString().split("\\.")[1];
System.out.println("[开方线程] √3 完整值: " + sqrt3);
// 输出小数点后10位数字
for (int i = 0; i < 10; i++) {
if (i < decimalPart.length()) {
char digit = decimalPart.charAt(i);
System.out.println("[开方线程] 小数点后第" + (i+1) + "位: " + digit);
} else {
System.out.println("[开方线程] 小数点后第" + (i+1) + "位: 0");
}
Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
}
// 只输出前10位小数
String result = decimalPart.length() >= 10 ? decimalPart.substring(0, 10) : decimalPart;
System.out.println("\n[开方线程] 最终结果: √3 ≈ " + result);
}
}
// 通用回调处理
static class LoggingCallback implements FutureCallback<Object> {
@Override
public void onSuccess(Object result) {
// 任务成功完成,无需特别处理
}
@Override
public void onFailure(Throwable t) {
System.err.println("任务失败: " + t.getMessage());
t.printStackTrace();
}
}
}
练习2
和练习1一样,对线程的执行顺序有要求,要求线程1执行一半时执行线程2,线程2执行一半时执行线程3,等待线程3执行完毕后再执行线程2,线程2执行完毕后执行线程1,要求分清不同线程的执行过程
答案:
package org.example;
import com.google.common.util.concurrent.*;
import java.math.BigDecimal;