第46天学习打卡(四大函数式接口 Stream流式计算 ForkJoin 异步回调 JMM Volatile)
池的最大的大小如何去设置!
了解:IO密集型,CPU密集型:(调优)
//1.CPU密集型 几核就是几个线程 可以保持效率最高
//2.IO密集型判断你的程序中十分耗IO的线程,只要大于这个线程数就行 一般设置为这个耗IO线程数的两倍
package com.kuang.pool;
import java.util.concurrent.*;
// Executors工具类 三大方法
//使用了线程池之后,使用线程池来创建线程
public class Demo01 {
public static void main(String[] args) {
//1.CPU密集型 几核就是几个线程 可以保持效率最高
//2.IO密集型判断你的程序中十分耗IO的线程,只要大于这个线程数就行 一般设置为这个耗IO线程数的两倍
System.out.println(Runtime.getRuntime().availableProcessors());//获取CPU的核数
ExecutorService threadPool = new ThreadPoolExecutor(2,
Runtime.getRuntime().availableProcessors(),
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常
try {
//最大承载:Deque + max
//RejectedExecutionException超出最大承载抛出的异常
for (int i = 1; i <= 9 ; i++) {
//使用了线程池之后,使用线程池来创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池用完,程序结束,关闭线程池
threadPool.shutdown();
}
}
}
12四大函数式接口(必须掌握)
函数式接口:只有一个方法接口。


Function函数式接口
package com.kuang.function;
import java.util.function.Function;
/**
* Function 函数型接口,有一个输入参数,有一个输出
* 只要是函数型接口,可以用Lambda表达式简化
*/
public class Demo01 {
public static void main(String[] args) {
//工具类:输出输入的值
///Function<String,String> function = new Function<String,String>() {
// @Override
// public String apply(String str) {
// return str;
// }
// };
//可以用Lambda表达式简化
Function<String,String> function = (str)->{return str;};
System.out.println(function.apply("asd"));
}
}
简化的lambda表达式
package com.kuang.function;
import java.util.function.Function;
/**
* Function 函数型接口,有一个输入参数,有一个输出
* 只要是函数型接口,可以用Lambda表达式简化
*/
public class Demo01 {
public static void main(String[] args) {
//工具类:输出输入的值
///Function<String,String> function = new Function<String,String>() {
// @Override
// public String apply(String str) {
// return str;
// }
// };
//可以用Lambda表达式简化
Function<String,String> function = str->{return str;};
System.out.println(function.apply("asd"));
}
}

断定型接口:有一个输入参数,返回值只能是布尔值!
package com.kuang.function;
import java.util.function.Predicate;
/**
* 断定型接口:有一个输入参数,返回值只能是布尔值
*/
public class Demo02 {
public static void main(String[] args) {
//判断字符串是否为空
// Predicate<String> predicate = new Predicate<String>(){
// @Override
// public boolean test(String str) {
// return str.isEmpty();
// }
// };
Predicate<String> predicate = (str)->{return str.isEmpty();};
System.out.println(predicate.test(""));
}
}
Consumer消费接口

package com.kuang.function;
import java.util.function.Consumer;
/**
*Consumer 消费接口:只有输入,没有返回值
/
public class Demo03 {
public static void main(String[] args) {
// Consumer<String> consumer = new Consumer<String>(){
// @Override
// public void accept(String str) {
// System.out.println(str);
// }
// };
Consumer<String> consumer = (str)->{
System.out.println(str);
};
consumer.accept("sad");
}
}
Supplier供给型接口

package com.kuang.function;
import java.util.function.Supplier;
/**
*Supplier 供给型接口 没有参数,只有返回值
*/
public class Demo04 {
public static void main(String[] args) {
//Supplier supplier = new Supplier<Integer>() {
// @Override
// public Integer get() {
// System.out.println("get()");
// return 1024;
// }
// };
Supplier supplier = ()->{return 1024; };
System.out.println(supplier.get());
}
}
13.Stream流式计算
什么是Stream流式计算
大数据:存储 + 计算
集合、MySQL本质就是存储东西的;
计算都应该交给流来操作!

运行时出现的问题:
java: 无法将类 com.kuang.stream.User中的构造器 User应用到给定类型;
解决方法:

package com.kuang.stream;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
package com.kuang.stream;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
/**
* 题目要求:一分钟内完成此题,只能用一行代码实现!
* 1.ID必须是偶数
* 2.年龄必须大于23岁
* 3.用户名转为大写字母
* 4.用户名字母倒着排序
* 5.只输出一个用户!
*/
public class Test {
public static void main(String[] args) {
User u1 = new User(1,"a",21);
User u2 = new User(2,"b",22);
User u3 = new User(3,"c",23);
User u4 = new User(4,"d",24);
User u5 = new User(6,"e",25);
//集合就是存储
List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
//计算交给Stream流
//链式编程 lambda表达式 函数式接口 Stream流
list.stream().filter(u->{return u.getId()%2==0;})
.filter(u->{return u.getAge()>23;} )
.map(u->{return u.getName().toUpperCase();})
.sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
.limit(1)
.forEach(System.out::println);
}
}
14 ForkJoin
分支合并
ForkJoin 在JDL1.7 并行执行任务!提高效率,大数据量!
大数据:Map Reduce(把大任务拆分为小任务)

ForkJoin特点:工作窃取(B做完后把A没有做完的拿过来做)
这个里面 维护的都是双端队列

ForkJoin的操作



package com.kuang.forkjoin;
import java.util.concurrent.RecursiveTask;
/**
* 求和计算的任务
* 如何使用forkjoin
* 1.forkjoinPool通过它来执行
* 2.计算任务forkjoinPool.execute(ForkJoinTask task)
*3.计算类要继承ForkJoinTask
*/
public class ForkJoinDemo extends RecursiveTask<Long>{
private Long start;
private Long end;
//临界值
private Long temp = 10000L;
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
//计算方法
package com.kuang.forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// test1();//执行的时间5867
//test2();//执行时间4332
test3();//sum=时间:152
}
public static void test1(){
Long sum = 0L;
long start = System.currentTimeMillis();
for (Long i = 1L; i <= 10_0000_0000; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("sum="+sum+" 时间:"+(end-start));
}
//会使用ForkJoin
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinDemo(0L, 10_0000_0000L);
// forkJoinPool.execute(task);//执行任务 但是没有结果
ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务有结果
Long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println("sum="+sum+"时间:"+(end-start));
}
public static void test3(){
long start = System.currentTimeMillis();
//Stream并行流 range():范围都是开括号 rangeClosed(]范围是开闭
long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
long end = System.currentTimeMillis();
System.out.println("sum="+"时间:"+(end-start));
}
