重新看JUC课程,选择周阳讲的JUC
Lombok是一个Java库,它通过注解的方式,能够在编译时自动为类生成构造函数、getters、setters、equals、hashCode和toString方法,以及其他常用方法,从而使我们的代码更加简洁,更易于阅读和编写。
@AllArgsConstructor
:这个注解会生成一个包含所有字段的构造函数,这个构造函数的参数顺序与字段在类中声明的顺序一致。@NoArgsConstructor
:这个注解会生成一个无参数的默认构造函数。@Data
:这个注解包含了@ToString,@EqualsAndHashCode,@Getter/@Setter和@RequiredArgsConstructor的功能,即:为类提供读写属性,同时生成equals,canEqual,hashCode,toString方法,以及参数为final的构造方法。所以,如果一个类被@Data注解,那么这个类就拥有了以上这些基本的数据操作功能。在Java 8中,方法引用是一种简化Lambda表达式的写法。方法引用可以更简洁、更直观地表示现有的方法、构造方法或者特定类型的任意对象的实例方法。
方法引用有以下四种形式:
// Lambda 表达式
Consumer<String> lambdaConsumer = (String s) -> System.out.println(s);
// 方法引用
Consumer<String> methodRefConsumer = System.out::println;
String str = "abc";
Predicate<String> lambdaPredicate = (String s) -> str.startsWith(s);
Predicate<String> methodRefPredicate = str::startsWith;
Predicate<String> lambdaPredicate = (String s) -> s.isEmpty();
Predicate<String> methodRefPredicate = String::isEmpty;
Supplier<List<String>> lambdaSupplier = () -> new ArrayList<>();
Supplier<List<String>> methodRefSupplier = ArrayList::new;
总的来说,方法引用是一种让你可以重复使用已有方法的功能。在许多情况下,它们可以使你的代码更简洁、更清晰。
Thread::start(native_ thread);
os::start_ thread(thread);
// 操作系统提供分配的线程
synchronized(Monitor){} // monitor就是一个监视器,也就是一个锁
public final boolean isDaemon() {
return daemon;
}
Future接口(FutureTask实现类)定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。
比如主线程让一个子线程去执行任务,子线程可能比较耗时,启动子线程开始执行任务后,主线程就去做其他事情了,忙其它事情或者先执行完,过了一会才去获取子任务的执行结果或变更的行务状态。
Future又称异步任务接口:
一句话:Future接口可以为主线程开一个分支任务,专门为主线程处理耗时和费力的复杂业务。
// 如何获得一个带有返回值的异步多线程任务,结合Thread类,并且获得处理结果
public class MyCompletableFutrueDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<>(new MyThread());
Thread t1 = new Thread(futureTask,"t1");
t1.start();
// 获取异步执行结果
System.out.println(futureTask.get());
}
}
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("come in callable");
return "hello world";
}
}
ExecutorService threadPool = Executors.newFixedThreadPool(3);
FutureTask<String> futureTask1 = new FutureTask<>(() -> {
try {TimeUnit.MICROSECONDS.sleep(500); } catch (InterruptedException e) {e.printStackTrace();}
return "task1 over";
});
threadPool.submit(futureTask1);
futureTask1.get();
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
},threadPool);
System.out.println(completableFuture.get());
CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
return "hello world";
}, threadPool);
System.out.println(completableFuture2.get());
threadPool.shutdown();
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
try {
CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName() + "come in");
int result = ThreadLocalRandom.current().nextInt(10);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1秒钟之后出结果!");
return result;
},fixedThreadPool).whenComplete((result,exception)->{
System.out.println("计算完成!——:"+result);
}).exceptionally(e->{
e.printStackTrace();
System.out.println("异常情况:"+e.getCause()+" "+e.getMessage());
return null;
});
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
fixedThreadPool.shutdown();
}
// 主线程不能立刻结束,否则CompletableFuture就以使用的线程池会立刻关闭:暂停3秒钟线程
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
复习:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
@FunctionalInterface
public interface Supplier<T> {
T get();
}
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
函数式接口名称 | 方法名称 | 参数 | 返回值 |
---|---|---|---|
Runnable | run | 无参数 | 无返回值 |
Function | apply | 1个参数 | 有返回值 |
Consumer | accept | 1个参数 | 无返回值 |
Supplier | get | 无参数 | 有返回值 |
BiComsumer | accept | 2个参数 | 无返回值 |
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
class Student{
private Integer id;
private String studentName;
private String major;
}
public static void main(String[] args) {
Student student = new Student();
// 链式调用
student.setId(12).setStudentName("mike").setMajor("CS");
}
public static List<String> getPriceByASync(List<NetMall> list,String productName) {
return list
.stream()
.map(netMall ->
CompletableFuture.supplyAsync(() ->
String.format(productName + " is %s price is %.2f",
netMall.getMallName(),
netMall.calcPrice(productName)))) //Stream>
.collect(Collectors.toList()) // List>
.stream() // Stream>
.map(CompletableFuture::join) //Stream
.collect(Collectors.toList()); // List
}
以上是周阳代码,不知道为什么不这么写,减少一次来回转换
public static List<String> getPriceByASync(List<NetMall> list,String productName) {
return list
.stream()
.map(netMall -> CompletableFuture.supplyAsync(()->
String.format(String.format(productName + " is %s price is %.2f",
netMall.getMallName(),
netMall.calcPrice(productName)))).join())
.collect(Collectors.toList());
}
然后自己去测试了一下:
后面的写法看似简单,实则失去了异步队列的优势,而是一个一个去执行,并且等待join,然后映射成新的值,相当于异步任务退化成串行化执行,耗时差距非常大!!
// code
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//暂停几秒钟线程
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
return 1;
},threadPoolExecutor);
System.out.println(future.get());
System.out.println(future.get(2L,TimeUnit.SECONDS));
System.out.println(future.getNow(9999));
System.out.println(future.complete(-44)+"\t"+future.get());
System.out.println(CompletableFuture.supplyAsync(() -> {
return 1;
}).thenApply(f -> {
return f + 2;
}).thenApply(f -> {
return f + 3;
}).whenComplete((v, e) -> {
if (e == null) {
System.out.println("0-------result: " + v);
}
}).exceptionally(e -> {
e.printStackTrace();
System.out.println(e.getMessage());
return null;
}).join());
System.out.println(CompletableFuture.supplyAsync(() -> {
return 1;
}).handle((f,e) -> {
System.out.println("-----1");
return f + 2;
}).handle((f,e) -> {
System.out.println("-----2");
return f + 3;
}).handle((f,e) -> {
System.out.println("-----3");
return f + 4;
}).whenComplete((v, e) -> {
if (e == null) {
System.out.println("----result: " + v);
}
}).exceptionally(e -> {
e.printStackTrace();
return null;
}).join());
CompletableFuture.supplyAsync(() -> {
return 1;
}).thenApply(f -> {
return f+2;
}).thenApply(f -> {
return f+3;
}).thenAccept(System.out::println);
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {}).join()); // A忙完了忙B,两者没有依赖,只是有顺序关系
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept(resultA -> {}).join()); // A忙完了,B需要A的结果,有顺序也有依赖关系,但是B无返回值
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(resultA -> resultA + " resultB").join()); // B需要A的结果,并且还有返回值
System.out.println(CompletableFuture.supplyAsync(() -> {
//暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 2;
}), r -> r + " is winner ").join());
System.out.println(CompletableFuture.supplyAsync(() -> {
return 10;
}).thenCombine(CompletableFuture.supplyAsync(() -> {
return 20;
}), (r1, r2) -> {
return r1 + r2;
}).join());