diff --git a/tp-admin/src/main/java/com/inscloudtech/web/controller/system/TestReportController.java b/tp-admin/src/main/java/com/inscloudtech/web/controller/system/TestReportController.java index 16529ab..d3b3201 100644 --- a/tp-admin/src/main/java/com/inscloudtech/web/controller/system/TestReportController.java +++ b/tp-admin/src/main/java/com/inscloudtech/web/controller/system/TestReportController.java @@ -78,7 +78,7 @@ public class TestReportController { } /** - * 上传测试报告 + * 上传测试报告/文件加密 * */ @Log(title = "测试报告管理", businessType = BusinessType.INSERT) diff --git a/tp-admin/src/main/resources/application.yml b/tp-admin/src/main/resources/application.yml index dfce8b0..ff4e643 100644 --- a/tp-admin/src/main/resources/application.yml +++ b/tp-admin/src/main/resources/application.yml @@ -73,9 +73,9 @@ spring: servlet: multipart: # 单个文件大小 - max-file-size: 1024MB + max-file-size: 10240MB # 设置总上传的文件大小 - max-request-size: 1024MB + max-request-size: 10240MB # 服务模块 devtools: restart: diff --git a/tp-functional/src/main/java/com/inscloudtech/functional/controller/demo/BestParallelController.java b/tp-functional/src/main/java/com/inscloudtech/functional/controller/demo/BestParallelController.java new file mode 100644 index 0000000..1c46165 --- /dev/null +++ b/tp-functional/src/main/java/com/inscloudtech/functional/controller/demo/BestParallelController.java @@ -0,0 +1,234 @@ +package com.inscloudtech.functional.controller.demo; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; + +/** + * Java 最强并行(I/O密集型)方法 + * @author aoe + * @date 2021/2/20 + */ + +@Slf4j +@RestController +@RequestMapping("/demo/bestParallel") +public class BestParallelController { + + private final List shops = getShops(100); + + private final Executor executor = + Executors.newFixedThreadPool(Math.min(shops.size(), 100), r -> { + Thread t = new Thread(r); + t.setDaemon(true); + return t; + }); + + public static void main(String[] args) { + BestParallelController test = new BestParallelController(); + + // 创建一个线程来执行CPU密集型任务 + Thread cpuIntensiveThread = new Thread(() -> { + long startTime = System.nanoTime(); + + // 模拟CPU密集型操作 + for (int i = 0; i < 1_000_000_000; i++) { + // 进行一些计算 + long sum = 0; + for (int j = 0; j < 1_000_000_000; j++) { + sum += j; + } + } + + long endTime = System.nanoTime(); + long duration = (endTime - startTime) / 1_000_000; // 转换为毫秒 + + System.out.println("CPU密集型任务完成,耗时:" + duration + "毫秒"); + }); + + // 启动线程 + cpuIntensiveThread.start(); + + long start = System.nanoTime(); + test.findPrices("car"); + long duration = (System.nanoTime() - start) / 1_000_000; + System.out.println("普通版 done in " + duration + " msecs"); + // 15115 + + start = System.nanoTime(); + test.findPricesBest("car"); + duration = (System.nanoTime() - start) / 1_000_000; + System.out.println("最强版 done in " + duration + " msecs"); + // 1020 + + + + + } + + public List findPrices(String product) { + List> priceFutures = + shops.stream() + // 使用 CompletableFuture 以异步方式及时每种商品的价格 + .map(shop -> CompletableFuture.supplyAsync(() -> shop.getName() + " price is" + shop.getPrice(product)) + ) + .collect(Collectors.toList()); + return priceFutures.stream() + // 等待所有异步操作结束 + .map(CompletableFuture::join) + .collect(Collectors.toList()); + } + + public List findPricesBest(String product) { + List> priceFutures = + shops.stream() + // 使用 CompletableFuture 以异步方式及时每种商品的价格 + .map(shop -> CompletableFuture.supplyAsync(() -> shop.getName() + " price is" + shop.getPrice(product), executor) + ) + .collect(Collectors.toList()); + return priceFutures.stream() + // 等待所有异步操作结束 + .map(CompletableFuture::join) + .collect(Collectors.toList()); + } + + private List getShops(int count) { + List list = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + list.add(new Shop("Shop" + i)); + } + return list; + } +} + +class Shop { + + private final String name; + private final Random random; + + public Shop(String name) { + this.name = name; + random = new Random(name.charAt(0) * name.charAt(1) * name.charAt(2)); + } + + public String getPrice(String product) { + double price = calculatePrice(product); + Discount.Code code = Discount.Code.values()[random.nextInt(Discount.Code.values().length)]; + return name + ":" + price + ":" + code; + } + + public double calculatePrice(String product) { + Util.delay(); + return Util.format(random.nextDouble() * product.charAt(0) + product.charAt(1)); + } + + public String getName() { + return name; + } + +} + +class Discount { + + public enum Code { + NONE(0), SILVER(5), GOLD(10), PLATINUM(15), DIAMOND(20); + + private final int percentage; + + Code(int percentage) { + this.percentage = percentage; + } + } + + public static String applyDiscount(Quote quote) { + return quote.getShopName() + " price is " + Discount.apply(quote.getPrice(), quote.getDiscountCode()); + } + + private static double apply(double price, Code code) { + Util.delay(); + return Util.format(price * (100 - code.percentage) / 100); + } +} + +class Util { + + private static final Random RANDOM = new Random(0); + private static final DecimalFormat formatter = new DecimalFormat("#.##", new DecimalFormatSymbols(Locale.US)); + + public static void delay() { + int delay = 1000; + //int delay = 500 + RANDOM.nextInt(2000); + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public static double format(double number) { + synchronized (formatter) { + return new Double(formatter.format(number)); + } + } + + public static CompletableFuture> sequence(List> futures) { +/* + CompletableFuture allDoneFuture = + CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])); + return allDoneFuture.thenApply(v -> + futures.stream() + .map(future -> future.join()) + .collect(Collectors.toList()) + ); +*/ + return CompletableFuture.supplyAsync(() -> futures.stream() + .map(future -> future.join()) + .collect(Collectors.toList())); + } + +} + +class Quote { + + private final String shopName; + private final double price; + private final Discount.Code discountCode; + + public Quote(String shopName, double price, Discount.Code discountCode) { + this.shopName = shopName; + this.price = price; + this.discountCode = discountCode; + } + + public static Quote parse(String s) { + String[] split = s.split(":"); + String shopName = split[0]; + double price = Double.parseDouble(split[1]); + Discount.Code discountCode = Discount.Code.valueOf(split[2]); + return new Quote(shopName, price, discountCode); + } + + public String getShopName() { + return shopName; + } + + public double getPrice() { + return price; + } + + public Discount.Code getDiscountCode() { + return discountCode; + } + +}