並行與併發
並行:多個機器同時執行
併發:一個機器分時執行
Future接口
定義了操作異步任務執行的一些方法,獲取異步任務執行的結果,取消任務的執行,判斷任務是否被取消,判斷任務執行完畢。
多線程/有返回/異步任務
class MyThread2 implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("execute");
return "hello";
}
}
public class aa {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask futureTask=new FutureTask(new MyThread2());
System.out.println(futureTask.isDone());
futureTask.run();
System.out.println(futureTask.isDone());
System.out.println(futureTask.get());
}
}
使用線程池
public class FutureThreadPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
Long startTime=System.currentTimeMillis();
FutureTask<String> futureTask1 = new FutureTask<>(() -> {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
return "futureTask1 success";
});
threadPool.submit(futureTask1);
FutureTask<String> futureTask2 = new FutureTask<>(() -> {
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
return "futureTask1 success";
});
threadPool.submit(futureTask2);
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
futureTask1.get();
futureTask2.get();
Long endTime=System.currentTimeMillis();
System.out.println(endTime-startTime);
threadPool.shutdown();
}
}
問題:
-
假如果get放在主線程前面,會阻塞主線程。
get(long time,TimeUnit unit)
超時便拋出異常 -
輪詢會導致CPU空轉。
while(!futureTask.isDone()){
}
futureTask1.get();
注意:回調通知,便不需要輪詢。
使用CompletableFuture,異步回調。
public class CompletableFutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName());
return "hello";
}, threadPool);
System.out.println(completableFuture.get());
}
}
public class CompletableFutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
CompletableFuture<String> step1 = CompletableFuture.supplyAsync(() -> {
System.out.println("step1 come in");
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("step1 run end");
return "step1";
},threadPool).whenComplete((v, e) -> {
if (e == null) {
System.out.println("步驟1 結束");
step2();
}
}).exceptionally(e -> {
e.printStackTrace();
return null;
});
System.out.println("主線程");
}
private static void step2() {
CompletableFuture<String> comeIn = CompletableFuture.supplyAsync(() -> {
System.out.println("step2 come in");
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("step2 run end");
return "step2";
});
try {
System.out.println(comeIn.get());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
}
電商比價需求:
public class MallTest {
static List<NetMall> list = Arrays.asList(new NetMall("jd"), new NetMall("dd"), new NetMall("tb"));
//public static List<String> getPrice(List<NetMall> list, String product) {
// return list.stream().map(netMall -> product + " in " + netMall.getNetMall() + " " + netMall.getPrice(product)).collect(Collectors.toList());
//}
public static List<String> getPrice(List<NetMall> list, String product) {
return list.stream()
.map(netMall -> CompletableFuture.supplyAsync(() -> product + " in " + netMall.getNetMall() + " " + netMall.calPrice(product)))
.collect(Collectors.toList())
.stream()
.map(t->t.join())
.collect(Collectors.toList());
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
long startTime = System.currentTimeMillis();
List<String> list1 = getPrice(list, "mysql");
for (String s : list1) {
System.out.println(s);
}
long endTime = System.currentTimeMillis();
System.out.println("執行時間:" + (endTime - startTime));
}
}
@Data
@AllArgsConstructor
class NetMall {
private String netMall;
public BigDecimal calPrice(String productName) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return BigDecimal.valueOf(ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0));
}
}