一、并发编程
1、Fork/Join分支合并框架
Fork/Join它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出。Fork/Join框架要完成两件事情:
Fork:把一个复杂任务进行分拆,大事化小
Join:把分拆任务的结果进行合并
RecursiveTask 递归任务:继承后可以实现递归(自己调自己)调用的任务。
@since 1.7
public abstract class RecursiveTask<V> extends ForkJoinTask<V>
RecursiveTask构造方法:
1.RecursiveTask()
RecursiveTask方法:
1.protected abstract V compute():此任务执行的主要计算。
2.protected boolean exec():实现递归任务的执行约定。
3.V getRawResult():返回ForkJoinTask将返回的结果。join(),即使此任务异常完成,
或者如果未知此任务已完成,则为null。
4.protected void setRawResult(V value):强制返回给定的值作为结果。
-----------------------------------------------------------------------
ForkJoinTask<V>
@since 1.7
public abstract class ForkJoinTask<V> extends Object
implements Future<V>, Serializable
ForkJoinTask<V>构造方法:
1.ForkJoinTask()
ForkJoinTask<V>常用方法:
1.ForkJoinTask<V> fork():安排异步执行此任务。
2.V get():如有必要,等待计算完成,然后检索其结果。
3.V join():完成计算后返回计算结果。
-----------------------------------------------------------------------
ForkJoinPool
public class ForkJoinPool extends AbstractExecutorService
ForkJoinPool构造方法:
1.ForkJoinPool()
ForkJoinPool常用方法:
1.void execute(ForkJoinTask<?> task):安排(异步)执行给定任务。
2.void execute(Runnable task):在将来的某个时间执行给定的命令。
3.<T> ForkJoinTask<T> submit(Callable<T> task):提交一个返回值的任务以供执行,
并返回一个表示任务挂起结果的未来。
4.<T> ForkJoinTask<T> submit(ForkJoinTask<T> task):提交要执行的ForkJoinTask。
5.ForkJoinTask<?> submit(Runnable task):提交可运行任务以执行,并返回表示该任务的未来。
6.<T> ForkJoinTask<T> submit(Runnable task, T result):提交可运行任务以执行,
并返回表示该任务的未来。
7.void shutdown():启动有序关机,执行以前提交的任务,但不接受新任务。
Fork/Join示例:
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
//求1+2+3+....100。需要拆分任务不超过10个数进行相加拆分
public class ForkJoinDemo {
public static void main(String[] args) throws Exception {
MyTask myTask = new MyTask(0,100);
//创建分支合并池对象
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(myTask);
//获取最终合并之后结果
Integer result = forkJoinTask.get();
System.out.println(result);
//关闭池对象
forkJoinPool.shutdown();
}
}
@SuppressWarnings("serial")
class MyTask extends RecursiveTask<Integer>{
private static final Integer VALUE = 10;
private int begin;
private int end;
private int result;
public MyTask(int begin, int end) {
this.begin = begin;
this.end = end;
}
@Override
protected Integer compute() {
//判断
if ((end-begin) <= VALUE) {
for (int i = begin; i <= end; i++) {
result = result + i;
}
}else {
int middle = (begin+end)/2;
//拆分左边
MyTask task01 = new MyTask(begin, middle);
//拆分右边
MyTask task02 = new MyTask(middle+1, end);
//调用方法拆分
task01.fork();
task02.fork();
//合并结果
result = task01.join() +task02.join();
}
return result;
}
}
2、CompletableFuture异步回调
同步:
异步:
CompletableFuture异步回调示例:
import java.util.concurrent.CompletableFuture;
public class CompletableFutureDemo {
public static void main(String[] args) throws Exception {
//同步调用
CompletableFuture<Void> completableFuture1 = CompletableFuture.runAsync(()->{
System.out.println(Thread.currentThread().getName() + " :completableFuture1");
});
completableFuture1.get();
//异步调用
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName() + " :completableFuture2");
return 1024;
});
completableFuture2.whenComplete((t,u)->{
System.out.println("--t--"+t);//t:表示成功的返回值
System.out.println("--u--"+u);//u:表示失败异常的信息
}).get();
//异步调用
CompletableFuture<Integer> completableFuture3 = CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName() + " :completableFuture3");
//模拟异常
int i = 10/0;
return 1024;
});
completableFuture3.whenComplete((t,u)->{
System.out.println("--t--"+t);//t:表示成功的返回值
System.out.println("--u--"+u);//u:表示失败异常的信息
}).get();
}
}
实际开发中一般不会用CompletableFuture异步回调。都会使用MQ消息队列的方式。
Java 并发编程(五)-线程池
每天⽤⼼记录⼀点点。内容也许不重要,但习惯很重要!
一个程序员最重要的能力是:写出高质量的代码!!
有道无术,术尚可求也,有术无道,止于术。
无论你是年轻还是年长,所有程序员都需要记住:时刻努力学习新技术,否则就会被时代抛弃!