Fork-Join分治编程
文章目录
使用RecursiveAction分解任务
public class MyRecursiveAction extends RecursiveAction {
private int beginValue;
private int endValue;
public MyRecursiveAction(int beginValue,int endValue){
super();
this.beginValue=beginValue;
this.endValue=endValue;
}
@Override
protected void compute() {
System.out.println(Thread.currentThread().getName()+"-----------");
if (endValue-beginValue>2){
int middelNum=(beginValue+endValue)/2;
MyRecursiveAction leftAction=new MyRecursiveAction(beginValue,middelNum);
MyRecursiveAction rightAction=new MyRecursiveAction(middelNum+1,endValue);
this.invokeAll(leftAction,rightAction);
}else {
System.out.println("打印组合:"+beginValue+"-"+endValue);
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
ForkJoinPool pool=new ForkJoinPool();
pool.submit(new MyRecursiveAction(1,10));
Thread.sleep(5000);
}
}
运行结果
使用RecursiveTask实现字符串累加
public class MyRecursiveTask extends RecursiveTask<String> {
private int beginValue;
private int endValue;
public MyRecursiveTask(int beginValue,int endValue){
this.beginValue=beginValue;
this.endValue=endValue;
}
@Override
protected String compute() {
System.out.println(Thread.currentThread().getName()+"------------");
if (endValue-beginValue>2){
int middleValue=(beginValue+endValue)/2;
MyRecursiveTask leftTask=new MyRecursiveTask(beginValue,middleValue);
MyRecursiveTask rightTask=new MyRecursiveTask(middleValue+1,endValue);
this.invokeAll(leftTask,rightTask);
return leftTask.join()+rightTask.join();
}else {
String returnString="";
for (int i=beginValue;i<endValue;i++){
returnString+=returnString+(i);
}
System.out.println("else 返回"+returnString+" "+beginValue+" "+endValue);
return returnString;
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
ForkJoinPool pool=new ForkJoinPool();
MyRecursiveTask task=new MyRecursiveTask(1,20);
ForkJoinTask<String> runTaskA=pool.submit(task);
System.out.println(runTaskA.join()+"=========");
Thread.sleep(5000);
}
}
使用Fork-Join实现求和
public class MyRecursiveTask extends RecursiveTask<Integer> {
private int beginPosition;
private int endPosition;
public MyRecursiveTask(int beginPosition,int endPosition){
super();
this.beginPosition=beginPosition;
this.endPosition=endPosition;
System.out.println("#"+(beginPosition+" "+endPosition));
}
@Override
protected Integer compute() {
Integer sumValue=0;
System.out.println("compute="+beginPosition+" "+endPosition);
if ((endPosition-beginPosition)>2){
System.out.println("!=0");
int middleNum=(endPosition+beginPosition)/2;
System.out.println("left传入的值"+(beginPosition+" "+middleNum));
MyRecursiveTask leftTask=new MyRecursiveTask(beginPosition,middleNum);
System.out.println("right传入的值:"+(middleNum+1)+" "+endPosition);
MyRecursiveTask rightTask=new MyRecursiveTask(middleNum+1,endPosition);
System.out.println("==========");
this.invokeAll(leftTask,rightTask);
Integer leftValue=leftTask.join();
Integer rightValue=rightTask.join();
return leftValue+rightValue;
}else {
int count=0;
for(int i=beginPosition;i<=endPosition;i++){
count=count+i;
}
return count;
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyRecursiveTask task=new MyRecursiveTask(1,10);
ForkJoinPool pool=new ForkJoinPool();
System.out.println("结果值: "+pool.submit(task).get());
}catch (Exception e){
e.printStackTrace();
}
}
}
运行结果
#1 10
compute=1 10
!=0
left传入的值1 5
#1 5
right传入的值:6 10
#6 10
==========
compute=1 5
!=0
left传入的值1 3
#1 3
right传入的值:4 5
#4 5
==========
compute=1 3
compute=4 5
compute=6 10
!=0
left传入的值6 8
#6 8
right传入的值:9 10
#9 10
==========
compute=6 8
compute=9 10
结果值: 55
在ForkJoinPool.java类中的execute()方法是以异步的方式执行任务。
public class Run2 {
public static void main(String[] args) {
try {
ForkJoinPool pool=new ForkJoinPool();
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("THreadName="+Thread.currentThread().getName());
}
});
Thread.sleep(5000);
}catch (Exception e){
e.printStackTrace();
}
}
}
方法public void execute(ForkJoinTask<? > task)如何处理返回值
public class MyRecursiveTask extends RecursiveTask<String> {
@Override
protected String compute() {
try {
Thread.sleep(5000);
}catch (Exception e){
e.printStackTrace();
}
return "我是返回值";
}
}
public class Run {
public static void main(String[] args) {
try {
MyRecursiveTask myRecursiveTask=new MyRecursiveTask();
ForkJoinPool pool=new ForkJoinPool();
pool.execute(myRecursiveTask);
System.out.println(System.currentTimeMillis());
System.out.println(myRecursiveTask.get());
System.out.println(System.currentTimeMillis());
Thread.sleep(5000);
}catch (Exception e){
e.printStackTrace();
}
}
}
方法public ForkJoinTasksubmit(ForkJoinTask task)的使用方法execute()无返回值,submit()有返回值
方法public List<Future> invokeAll(Collection<?extends Callable> tasks)具有阻塞特性。
public class MyCallable implements Callable<String> {
private long sleepValue;
public MyCallable(long sleepValue){
super();
this.sleepValue=sleepValue;
}
@Override
public String call() throws Exception {
try {
System.out.println(Thread.currentThread().getName()+" sleep"+sleepValue+" nowTime"+System.currentTimeMillis());
Thread.sleep(sleepValue);
}catch (Exception e){
e.printStackTrace();
}
return "我是返回值";
}
}
public class Test {
public static void main(String[] args) {
try {
List list=new ArrayList<>();
list.add(new MyCallable(5000));
list.add(new MyCallable(4000));
list.add(new MyCallable(3000));
list.add(new MyCallable(2000));
list.add(new MyCallable(1000));
ForkJoinPool pool=new ForkJoinPool();
List<Future<String>> listFuture=pool.invokeAll(list);//阻塞
for (int i=0;i<listFuture.size();i++){
System.out.println(listFuture.get(i).get()+" nowTime"+System.currentTimeMillis());
}
}catch (Exception e){
e.printStackTrace();
}
}
}
方法public void shutdown()的使用
public class MyRunnable1 implements Runnable {
@Override
public void run() {
try {
System.out.println("begin "+Thread.currentThread().getName()+System.currentTimeMillis());
Thread.sleep(4000);
System.out.println("end "+Thread.currentThread().getName()+" "+System.currentTimeMillis());
}catch (Exception e){
e.printStackTrace();
}
}
}
public class Test1 {
public static void main(String[] args) throws InterruptedException {
MyRunnable1 myRunnable1=new MyRunnable1();
ForkJoinPool pool=new ForkJoinPool();
pool.submit(myRunnable1);
Thread.sleep(1000);
pool.shutdown();
pool.submit(myRunnable1);
System.out.println("main end");
Thread.sleep(Integer.MAX_VALUE);
}
}
运行结果: 调用shutdown()之后线程不会马上停止,程序会继续执行完成
shutdown()之后,在调用销毁的线程会抛异常
方法public List shutdownNow()的使用
public class MyRunnable1 implements Runnable {
@Override
public void run() {
try {
for (int i=0;i<Integer.MAX_VALUE;i++){
String newString=new String();
Math.random();
Math.random();
Math.random();
Math.random();
Math.random();
Math.random();
if (Thread.currentThread().isInterrupted()==true){
System.out.println("任务没有完成,就结束了");
throw new InterruptedException();
}
}
System.out.println("任务完成了");
}catch (Exception e){
System.out.println("进入catch中断了任务");
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
MyRunnable1 myRunnable1=new MyRunnable1();
ForkJoinPool pool=new ForkJoinPool();
pool.submit(myRunnable1);
Thread.sleep(2000);
pool.shutdownNow();
System.out.println("main end");
Thread.sleep(Integer.MAX_VALUE);
}
}
方法isTerminating()和isTerminated()的使用
返回ture线程池已销毁
public class Run1 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
Runnable runnable=new Runnable() {
@Override
public void run() {
for (int i=0;i<Integer.MAX_VALUE/100;i++){
String newString=new String();
Math.random();
Math.random();
Math.random();
Math.random();
Math.random();
Math.random();
}
}
};
ForkJoinPool pool=new ForkJoinPool();
ForkJoinTask task=pool.submit(runnable);
Thread.sleep(500);
System.out.println("A="+pool.isTerminating());
pool.shutdown();
System.out.println("B="+pool.isTerminating());
System.out.println(task.get());
Thread.sleep(1000);
System.out.println("C="+pool.isTerminated());
}
}
运行结果
方法awaitTermination(long timeout, TimeUnit unit)的作用是等待池被销毁的最长时间,具有阻塞特性。
public class MyRunnable1 implements Runnable {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" "+System.currentTimeMillis());
Thread.sleep(4000);
System.out.println(" end "+Thread.currentThread().getName()+" "+System.currentTimeMillis());
}catch (Exception e){
e.printStackTrace();
}
}
}
public class Test1 {
public static void main(String[] args) throws InterruptedException {
MyRunnable1 myRunnable1=new MyRunnable1();
ForkJoinPool pool=new ForkJoinPool();
pool.execute(myRunnable1);
pool.shutdown();//关闭线程池
System.out.println("main begin"+System.currentTimeMillis());
System.out.println(pool.awaitTermination(10, TimeUnit.SECONDS));//最多等待10秒,阻塞
System.out.println("main end "+System.currentTimeMillis());
//返回值打印false代表任务池并没有被销毁。
}
}
方法execute(task) submit(task) invoke(task)的区别?
方法execute(task)、submit(task)以及invoke(task)都可以在异步队列中执行任务,需要注意的是,方法invoke()是阻塞的,而它们在使用上的区别其实很简单,execute(task)只执行任务,没有返回值,而submit(task)方法有返回值,返回值类型是ForkJoinTask,想取得返回值时,需要使用ForkJoinTask对象的get()方法,而invoke(task)和submit(task)方法一样都具有返回值的功能,区别就是invoke(task)方法直接将返回值进行返回,而不是通过ForkJoinTask对象的get()方法。
监视pool池的状态
❑ 方法getParallelism():获得并行的数量,与CPU的内核数有关;
❑ 方法getPoolSize():获得任务池的大小;
❑ 方法getQueuedSubmissionCount():取得已经提交但尚未被执行的任务数量;
❑ 方法hasQueuedSubmissions():判断队列中是否有未执行的任务;
❑ 方法getActiveThreadCount():获得活动的线程个数;
❑ 方法getQueuedTaskCount():获得任务的总个数;
❑ 方法getStealCount():获得偷窃的任务个数;
❑ 方法getRunningThreadCount():获得正在运行并且不在阻塞状态下的线程个数;
❑ 方法isQuiescent():判断任务池是否是静止未执行任务的状态。
方法isCompletedAbnormally()判断任务是否出现异常,方法isCompletedNormally()判断任务是否正常执行完毕,方法getException()返回报错异常。