juc--Fork-Join分治编程

本文深入探讨Fork-Join框架的使用,包括RecursiveAction和RecursiveTask的实现,以及ForkJoinPool的主要方法如execute、submit和invoke。同时,文章还讲解了如何监控ForkJoinPool的状态,并提供了丰富的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()返回报错异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值