Java练习-----4、JavaMaven项目中对于执行大量任务时是否需要接受返回值来分别创建多线程提高执行效率


使用多线程执行大量任务提高执行效率


一 、执行方法后需要获取返回值
这种获取多线程返回值的方式有很大的缺点,那就是会导致线程阻塞,主线程必须等待该线程获取到返回值后才执行下一个,效率会大大降低。


导入依赖

<!--        // 使用hutool的NamedThreadFactory    线程工厂,主要用来创建线程-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.20</version>
        </dependency>

代码

package cn.zzz.idb.stream;


import cn.hutool.core.thread.NamedThreadFactory;
import java.util.*;
import java.util.concurrent.*;
/**
 * @Author: hjt
 * @Date: 2022/08/20/18:28
 * @Description:    使用多线程执行任务
 *              线程创建顺序  :   1.核心线程池:判断“核心线程池”是否已满,否,则创建线程执行任务;是,则移交“任务缓存队列”
 *                              2.任务缓存队列:判断“任务缓存队列”是否已满,否,则将任务存于“任务缓存队列”中;是,则移交“最大线程池”
 *                              3.最大线程池:判断“最大线程池”是否已满,否,则创建线程执行任务;是,则移交给“线程溢出任务处理策略”
 *                              4.线程溢出任务处理策略:按照指定的策略来处理无法执行的任务
 */
public class StreamTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 接收结果集
        List<Future<String>> futureList = new ArrayList<>();
        // 创建有界阻塞队列,防止内存溢出    任务缓存队列,即workQueue,它用来存放等待执行的任务。
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(3);
        // 使用hutool的NamedThreadFactory    线程工厂,主要用来创建线程  自定义线程前缀名   是否守护线程  String prefix, boolean isDaemon
        ThreadFactory threadFactory = new NamedThreadFactory("测试",false);
        // 任务拒绝策略        1  AbortPolicy策略           直接抛异常,阻止系统正常工作 是默认策略
        //                   2  CallerRunsPolicy策略      只用调用者所在的线程处理任务
        //                   3  DiscardOldestPolicy策略   丢弃等待队列中最旧的任务,并执行当前任务
        //                   4  DiscardPolicy策略         直接丢弃任务,但不抛出异常
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
                                                    //    核心线程数      <       最大线程数    线程没有任务时的存活时间
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2,4,3, TimeUnit.SECONDS,workQueue,threadFactory,handler);
        Long start = System.currentTimeMillis();
        for (int i = 0; i < 20; i++) {
            try{
                //  提交任务    submit()方法有一个返回值Future
                futureList.add(executor.submit(new Task()));
                System.out.println("当前排队线程数:= " + executor.getQueue().size());   //   最大值  为  任务缓存队列  长度
                System.out.println("当前活动线程数:= " + executor.getActiveCount());    //   最大值  为  核心线程池数  +  最大线程池数
                System.out.println("===============================");
            }catch (Exception e){
                System.out.println("异常");
            }
        }
        executor.shutdown();
        System.out.println("线程结束===============================");
        for (Future<String> stringFuture : futureList) {
            System.out.println(stringFuture.get());
        }
        Long end = System.currentTimeMillis();
        System.out.println(end-start);  // 5  361    10  180    15   139
    }

    /**
     *  无参多线程方法
     */
    public static class Task implements Callable<String>{

        @Override
        public String call() throws Exception {
            Thread.sleep(10);
            return Thread.currentThread().getName();
        }
    }

    /**
     *  传入参数  多线程方法
     *  无参构造方法中调用业务方法
     */
    public static class Task2 implements Callable<String>{

        private String name;

        private int age;

        public Task2(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String call() throws Exception {
            System.out.println("name = " + name);
            System.out.println("age = " + age);
            return Thread.currentThread().getName();
        }
    }

}
二 、执行方法后不获取返回值
package cn.zzz.idb.stream;

import cn.hutool.core.thread.NamedThreadFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Author: hjt
 * @Date: 2022/08/20/19:51
 * @Description:
 */
public class StreamTest2 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 创建有界阻塞队列,防止内存溢出    任务缓存队列,即workQueue,它用来存放等待执行的任务。
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(2);
        ThreadFactory threadFactory = new NamedThreadFactory("测试",false);
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
        // 线程计数器
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2,3,3, TimeUnit.SECONDS,workQueue,threadFactory,handler);
        Long start = System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            try{
                Task task = new Task();
                executor.execute(task);
                System.out.println("当前排队线程数:= " + executor.getQueue().size());   //   最大值  为  任务缓存队列  长度
                System.out.println("当前活动线程数:= " + executor.getActiveCount());    //   最大值  为  核心线程池数  +  最大线程池数
                System.out.println("===============================");
            }catch (Exception e){
                System.out.println("异常");
            }
        }
        executor.shutdown();
//        //当所有线程执行完毕后才继续执行后续代码
//        countDownLatch.countDown();
//        countDownLatch.await();
        System.out.println("线程结束===============================");
        Long end = System.currentTimeMillis();
        System.out.println(end-start);  // 5  361    10  180    15   139

    }

    /**
     *  无参多线程方法
     */
    public static class Task implements Runnable{

        @Override
        public void run() {
            try {
                Thread.sleep(10);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }



}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值