Java CountedCompleter 与 ForkJoinTask 的代码篇

在看 ConcurrentHashMap 的源码时,BulkTask extends CountedCompleter,CountedCompleter extends ForkJoinTask,那么我们也按照这个继承顺序,一探究竟。

1. invoke 看 ForkJoinTask 的各种状态值

  • 实体类
import java.util.concurrent.CountedCompleter;

public class MyForkJoinTask<R> extends CountedCompleter<R> {
    static int i = 1;
    public MyForkJoinTask() {
    }

    @Override
    public void compute() {
        try {
            /* 特定的设置为 EXCEPTIONAL */
            if(i == 2) completeExceptionally(new Exception());
        } catch (Exception e) {
            e.printStackTrace();
        }
        i++;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /* 不让 SIGNAL 设置完成*/
        if(i != 5) propagateCompletion();
    }
}
  • 测试类
import java.lang.reflect.Field;

public class MyForkJoinTaskTest01 {
    public static void main(String[] args) throws Exception {
        MyForkJoinTask<Object> myForkJoinTask01 = new MyForkJoinTask<>();
        MyForkJoinTask<Object> myForkJoinTask02 = new MyForkJoinTask<>();
        MyForkJoinTask<Object> myForkJoinTask03 = new MyForkJoinTask<>();
        MyForkJoinTask<Object> myForkJoinTask04 = new MyForkJoinTask<>();
        MyForkJoinTask<Object> myForkJoinTask05 = new MyForkJoinTask<>();
        MyForkJoinTask<Object> myForkJoinTask06 = new MyForkJoinTask<>();

        Field status01 =  myForkJoinTask01.getClass().getSuperclass().getSuperclass().getDeclaredField("status");
        Field status02 =  myForkJoinTask02.getClass().getSuperclass().getSuperclass().getDeclaredField("status");
        Field status03 =  myForkJoinTask03.getClass().getSuperclass().getSuperclass().getDeclaredField("status");
        Field status04 =  myForkJoinTask04.getClass().getSuperclass().getSuperclass().getDeclaredField("status");
        Field status05 =  myForkJoinTask05.getClass().getSuperclass().getSuperclass().getDeclaredField("status");
        Field status06 =  myForkJoinTask06.getClass().getSuperclass().getSuperclass().getDeclaredField("status");
        status01.setAccessible(true);
        status02.setAccessible(true);
        status03.setAccessible(true);
        status04.setAccessible(true);
        status05.setAccessible(true);
        status06.setAccessible(true);

        new Thread(() -> {
            try {
                Thread.sleep(500);
                System.out.println("=================");
                myForkJoinTask01.cancel(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        try{
            /* 半路取消,CANCELLED */
            myForkJoinTask01.invoke();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            /* 直接取消,CANCELLED */
            myForkJoinTask02.cancel(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            /* 设置成 EXCEPTIONAL */
            myForkJoinTask03.invoke();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            /* 正常执行完成 */
            myForkJoinTask04.invoke();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("================ myForkJoinTask01 ================");
        System.out.print("status: " + Integer.toHexString((Integer) status01.get(myForkJoinTask01)) + "\t CANCELLED   = 0xc0000000"+ "\t");
        System.out.print("isCancelled(): " + myForkJoinTask01.isCancelled() + " \t");
        System.out.print("isDone(): " + myForkJoinTask01.isDone() + "\t");
        System.out.print("isCompletedAbnormally(): " + myForkJoinTask01.isCompletedAbnormally() + "\t");
        System.out.print("isCompletedNormally(): " + myForkJoinTask01.isCompletedNormally() + "\t");
        System.out.println();
        System.out.println("================== myForkJoinTask02 ===================");
        System.out.print("status: " + Integer.toHexString((Integer) status02.get(myForkJoinTask02)) + "\t CANCELLED = 0xc0000000"+ "\t");
        System.out.print("isCancelled(): " + myForkJoinTask02.isCancelled() + "\t");
        System.out.print("isDone(): " + myForkJoinTask02.isDone() + "\t");
        System.out.print("isCompletedAbnormally(): " + myForkJoinTask02.isCompletedAbnormally() + "\t");
        System.out.print("isCompletedNormally(): " + myForkJoinTask02.isCompletedNormally() + "\t");
        System.out.println();
        System.out.println("================= myForkJoinTask03 ====================");
        System.out.print("status: " + Integer.toHexString((Integer) status03.get(myForkJoinTask03)) + "\t EXCEPTIONAL     = 0x80000000;"+ "\t");
        System.out.print("isCancelled(): " + myForkJoinTask03.isCancelled() + "\t");
        System.out.print("isDone(): " + myForkJoinTask03.isDone() + "\t");
        System.out.print("isCompletedAbnormally(): " + myForkJoinTask03.isCompletedAbnormally() + "\t");
        System.out.print("isCompletedNormally(): " + myForkJoinTask03.isCompletedNormally() + "\t");
        System.out.println();
        System.out.println("================= myForkJoinTask04 ====================");
        System.out.print("status: " + Integer.toHexString((Integer) status04.get(myForkJoinTask04)) + "\t NORMAL     = 0xf0000000;"+ "\t");
        System.out.print("isCancelled(): " + myForkJoinTask04.isCancelled() + "\t");
        System.out.print("isDone(): " + myForkJoinTask04.isDone() + "\t");
        System.out.print("isCompletedAbnormally(): " + myForkJoinTask04.isCompletedAbnormally() + "\t");
        System.out.print("isCompletedNormally(): " + myForkJoinTask04.isCompletedNormally() + "\t");
        System.out.println();
        System.out.println("================= myForkJoinTask05 ====================");
        System.out.print("status: " + Integer.toHexString((Integer) status05.get(myForkJoinTask05)) + "\t 初始化 status     = 0;"+ "\t");
        System.out.print("isCancelled(): " + myForkJoinTask05.isCancelled() + "\t");
        System.out.print("isDone(): " + myForkJoinTask05.isDone() + "\t");
        System.out.print("isCompletedAbnormally(): " + myForkJoinTask05.isCompletedAbnormally() + "\t");
        System.out.print("isCompletedNormally(): " + myForkJoinTask05.isCompletedNormally() + "\t");
        System.out.println();


        System.out.println("=============================================");
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("================= myForkJoinTask06 ====================");
                System.out.print("status: " + Integer.toHexString((Integer) status06.get(myForkJoinTask06)) + "\t SIGNAL     = 0x00010000;"+ "\t");
                System.out.print("isCancelled(): " + myForkJoinTask06.isCancelled() + "\t");
                System.out.print("isDone(): " + myForkJoinTask06.isDone() + "\t");
                System.out.print("isCompletedAbnormally(): " + myForkJoinTask06.isCompletedAbnormally() + "\t");
                System.out.print("isCompletedNormally(): " + myForkJoinTask06.isCompletedNormally() + "\t");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        try{
            /* invoke 执行 */
            System.out.println("myForkJoinTask06 开始执行");
            myForkJoinTask06.invoke();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

2. 为什么使用 invoke(),而不直接使用 compute() ?

  • 先说结论,invoke() 会等待全部任务完成,compute()执行完当前任务则退出。
  • 实体类
import java.util.concurrent.CountedCompleter;

public class MyForkJoinTask02<R> extends CountedCompleter<R> {
    int batch = 0;

    public MyForkJoinTask02(CountedCompleter<?> completer, int batch) {
        super(completer);
        this.batch = batch;
    }

    @Override
    public void compute() {
        for (;batch > 0;) {
            addToPendingCount(1);
            new MyForkJoinTask02<R>(this, batch >>>= 1).fork();
        }
        System.out.println("now batch = " + batch);
        propagateCompletion();
    }
}
  • 测试类
public class MyForkJoinTaskTest02 {
    public static void main(String[] args) throws InterruptedException {

        MyForkJoinTask02<Object> myForkJoinTask = new MyForkJoinTask02<>(null, 5);
        MyForkJoinTask02<Object> myForkJoinTask02 = new MyForkJoinTask02<>(null, 5);
        myForkJoinTask.invoke();
        System.out.println("========== 华丽分割线 =========");
        myForkJoinTask02.compute();
        System.out.println("===========================");
        myForkJoinTask02.join();

    }
}

在这里插入图片描述

3. 异常存储之 exceptionTable

  • 实体类
package cn.cerish.forkJoin;

import java.util.concurrent.CountedCompleter;

public class MyForkJoinTask03<R> extends CountedCompleter<R> {
    static int i = 0;
    int batch;
    public MyForkJoinTask03(CountedCompleter<?> completer, int batch) {
        super(completer);
        this.batch = batch;
    }
    /* 抛出不同种类的错误 */
    @Override
    public void compute() {
        i++;
        if(i == 1) completeExceptionally(new RuntimeException());
        if(i == 2) completeExceptionally(new NoSuchFieldException());
        if(i == 3) completeExceptionally(new IndexOutOfBoundsException());
    }
}
  • 测试类
import java.lang.reflect.Field;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class MyForkJoinTaskTest03 {
    public static void main(String[] args) throws Exception {

        MyForkJoinTask03<String> myForkJoinTask01 = new MyForkJoinTask03<>(null, 1);
        MyForkJoinTask03<String> myForkJoinTask02 = new MyForkJoinTask03<>(null, 1);
        MyForkJoinTask03<String> myForkJoinTask03 = new MyForkJoinTask03<>(null, 1);
        MyForkJoinTask03<String> myForkJoinTask04 = new MyForkJoinTask03<>(null, 1);
        Class<?> forkJoinTaskClass = myForkJoinTask01.getClass().getSuperclass().getSuperclass();
        Field exceptionTable = forkJoinTaskClass.getDeclaredField("exceptionTable");
        exceptionTable.setAccessible(true);
        try{
            myForkJoinTask01.invoke();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            myForkJoinTask02.invoke();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            myForkJoinTask03.invoke();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("====================== myForkJoinTask01 ====================");
        System.out.println("getException(): " + myForkJoinTask01.getException() + "\t");
        System.out.print("getCompleter(): " + myForkJoinTask01.getCompleter() + "\t");
        System.out.print("getForkJoinTaskTag(): " + myForkJoinTask01.getForkJoinTaskTag() + "\t");
        System.out.print("getPendingCount(): " + myForkJoinTask01.getPendingCount() + "\t");
        System.out.print("getRawResult(): " + myForkJoinTask01.getRawResult() + "\t");
        System.out.println();
        System.out.println("====================== myForkJoinTask02 ====================");
        System.out.println("getException(): " + myForkJoinTask02.getException() + "\t");
        System.out.print("getCompleter(): " + myForkJoinTask02.getCompleter() + "\t");
        System.out.print("getForkJoinTaskTag(): " + myForkJoinTask02.getForkJoinTaskTag() + "\t");
        System.out.print("getPendingCount(): " + myForkJoinTask02.getPendingCount() + "\t");
        System.out.print("getRawResult(): " + myForkJoinTask02.getRawResult() + "\t");
        System.out.println();
        System.out.println("===================== myForkJoinTask03 =======================");
        System.out.println("getException(): " + myForkJoinTask03.getException() + "\t");
        System.out.print("getCompleter(): " + myForkJoinTask03.getCompleter() + "\t");
        System.out.print("getForkJoinTaskTag(): " + myForkJoinTask03.getForkJoinTaskTag() + "\t");
        System.out.print("getPendingCount(): " + myForkJoinTask03.getPendingCount() + "\t");
        System.out.print("getRawResult(): " + myForkJoinTask03.getRawResult() + "\t");
        System.out.println();
        System.out.println("=============== myForkJoinTask04 用来查看 exceptionTable ===============");
        Object[] objects = (Object[]) exceptionTable.get(myForkJoinTask04);
        for (Object object : objects) {
            if(object != null) System.out.println(object);
        }
        myForkJoinTask03.reinitialize();
        System.out.println("=============== myForkJoinTask03.reinitialize() 清除错误状态 ===============");
        Object[] objects01 = (Object[]) exceptionTable.get(myForkJoinTask04);
        for (Object object : objects01) {
            if(object != null) System.out.println(object);
        }
    }
}

在这里插入图片描述

4. ForkJoinTask 中的 Runnable、Callable

import java.util.concurrent.ForkJoinTask;

public class MyForkJoinTaskTest04 {
    public static void main(String[] args) throws Exception {
        ForkJoinTask<?> adapt01 = ForkJoinTask.adapt(() -> {
            System.out.println("I am Runnable(), 我的返回值默认为null即没有返回值");
        });
        System.out.println("adapt01.invoke(): " + adapt01.invoke());
        System.out.println("================== 华丽分割线 ====================");
        ForkJoinTask<Integer> adapt02 = ForkJoinTask.adapt(() -> {
            System.out.println("I am Runnable(), 在下是有返回值的");
        }, 100);
        System.out.println("adapt02.invoke(): " + adapt02.invoke());
        System.out.println("================== 华丽分割线 ====================");
        ForkJoinTask<String> adapt03 = ForkJoinTask.adapt(() -> {
            System.out.println("I am Callable(), 在下是有返回值的,直接方法内返回");
            return "I am return value for Callable()";
        });
        System.out.println("adapt03.invoke(): " + adapt03.invoke());

    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值