请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

awaitTermination

老师,您好,想请教您个问题:
forkjoinpool线程池,为了保证线程池里的子线程优于主线程(main)先执行,只有当线程池中的子线程全部执行完再执行主线程,这里我使用awaitTermination(time,timeunit)方法。
可是,在线程池的子线程执行任务的时候,为什么main线程也会去执行任务,而不是单纯的在那等待?
图片描述

还有一个问题:
forkjoinpool线程池,在执行某个任务的时候创建了20个子线程帮助执行该任务。当该任务执行结束,那么在不关闭forkjoinpool线程池的情况下,这20个子线程会被GC回收吗?
望老师解惑,谢谢

正在回答

3回答

小伙伴的探索精神很好,就是因为Forkjoinpool不是new出来的,是因为ForkJoinPool pool = ForkJoinPool.commonPool();用公共线程池。这个就是公共线程池的特性,对于公共线程池来说,主线程也是可以用来执行任务的。

0 回复 有任何疑惑可以回复我~
  • 提问者 林就远 #1
    老师您好,有个很奇怪的地方。
    1)对于ForkJoinPool.commonPool()创建出来的公共线程池。执行awaitTermination(1,TimeUnit.Hour)方法,那么当公共线程池里的线程处理完了所提交的任务,那么就会放开阻塞,让主线程继续执行。而不必等待一个小时。
    2)对公共线程池执行awaitTermination(1,TimeUnit.Hour)之前执行shutdown(),和第一步一样,当公共线程池里的线程处理完任务之后才会继续走main线程的逻辑。不同点就是调用shutdown方法关闭了线程池。
    3)可是如果是对于new ForkJoinPool()形式创建出来的线程池,那么用该线程池对象调用awaitTermination(1,TimeUnit.HOUR),当线程池里的子线程处理完了任务,主线程还是阻塞状态的。我测试了下,需要等到过了超时时间(也就是设置的一小时)它才会继续走主线程。
    4)可如果我在创建的线程池调用awaitTermination(1,TimeUnit.HOUR)之前调用了shutdown(),那么在线程池的子线程处理完任务之后就会立即走主线程。
    5)疑惑的地方,为什么对于公共线程池和创建出来的线程池,在调用awaitTermination之前没有执行shutdown方法有这么大的差别?网上找了一些教程,说是awaitTermination要结合shutdown使用,可是我对于公共线程池的测试,我在调用awaitTermination之前没有调用shutdown的情况也可以保证等线程池任务结束再走主线程的逻辑部分。
    回复 有任何疑惑可以回复我~ 2020-11-25 10:38:50
  • 悟空 回复 提问者 林就远 #2
    你的3 4 ,是正常现象,线程池就应该是这样的,只不过commonPool特殊,请看commonPool方法的注释
        /**
         * Returns the common pool instance. This pool is statically
         * constructed; its run state is unaffected by attempts to {@link
         * #shutdown} or {@link #shutdownNow}. However this pool and any
         * ongoing processing are automatically terminated upon program
         * {@link System#exit}.  Any program that relies on asynchronous
         * task processing to complete before program termination should
         * invoke {@code commonPool().}{@link #awaitQuiescence awaitQuiescence},
         * before exit.
         *
         * @return the common pool instance
         * @since 1.8
    所以不使用commonPool即可,用我们自己的new ForkJoinPool()是最合适的。
    回复 有任何疑惑可以回复我~ 2020-11-25 15:44:40
提问者 林就远 2020-11-24 17:30:45
public static void main(String[] args) throws InterruptedException {
    ForkJoinPool pool = ForkJoinPool.commonPool();
    pool.submit(new Task(0,100));
    pool.awaitTermination(1,TimeUnit.HOURS);
    System.out.println(Thread.currentThread().getName() + "【我是来捣乱的】");
}

static class Task extends RecursiveAction{

    int n;
    int front;

    Task(int front, int n){
        this.front = front;
        this.n = n;
    }

    @Override
    protected void compute() {
        if ((n - front) < 5){
            for (int i = front; i < n; i++) {
                System.out.println(Thread.currentThread().getName() + " number:" + i + " 大帅比");
            }
        }
        else {
            Task frontHalfTask = new Task(front,(front + n) /2);
            Task backHalfTask = new Task((front + n) / 2, n);
            frontHalfTask.fork();
            backHalfTask.fork();
        }
    }
}


0 回复 有任何疑惑可以回复我~
提问者 林就远 2020-11-24 17:15:33

老师,我测出来是因为,我的Forkjoinpool不是new出来的,是因为ForkJoinPool pool = ForkJoinPool.commonPool();用公共线程池,可是为啥公共线程池就包含main线程呢。

0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号