异步线程执行以及线程返回值的使用

异步线程执行以及线程返回值的使用

使用CompletableFuture异步执行(有返回值)

1 supplyAsync方法

如果自己定义了线程的Executor的线程池的工具类,可以传入Executor类型的参数
 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        return asyncSupplyStage(ASYNC_POOL, supplier);
    }

    /**
     * Returns a new CompletableFuture that is asynchronously completed
     * by a task running in the given executor with the value obtained
     * by calling the given Supplier.
     *
     * @param supplier a function returning the value to be used
     * to complete the returned CompletableFuture
     * @param executor the executor to use for asynchronous execution
     * @param <U> the function's return type
     * @return the new CompletableFuture
     */
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }
1.1 使用CompletableFuture异步执行任务并得到返回值
package 多线程测试;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;

/**
 * @author
 * @desc  使用CompletableFuture创建线程使用返回值并执行
 * CompletableFuture用于异步编程,异步通常意味着非阻塞,使我们的任务单独运行在与主线程分离的其他线程中 ,并且通过回调可以在主线程中得到异步任务的执行状态 是否完成和是否异常等 并行方式
 * 不需要一直等到子线程完成 -- 优点:主线程可以并行的执行其他任务 提高性能
 * @date
 */
public class ThreadTest {

    // 使用CompletableFuture创建线程使用返回值并执行
    public static void main(String[] args) {
        ArrayList<String> partions = new ArrayList();
        //supplyAsync(Supplier)
        CompletableFuture<List<String>> future = CompletableFuture.supplyAsync(new Supplier<>() {
            @Override
            public List<String> get() {
                //对
                return new ArrayList<>();
            }
        });

        //supplyAsync(Supplier,Executor 自己写的线程工具类)
        CompletableFuture<List<String>> future1 = CompletableFuture.supplyAsync(new Supplier<>() {
            @Override
            public List<String> get() {
                //对list进行处理
                return new ArrayList<>();
            }
        },ThreadUtils.achieveThread());

        //收集线程返回值  CompletableFuture的get方法   主线程(程序跑的话 总会收集全 但是主线程不会阻塞)
        try {
            List<String> strings = future.get();
            System.out.println(strings);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

/**
 * @author
 * @desc 线程池工具类  ThreadPoolExecutor
 * @date
 */
@Slf4j
public class ThreadUtils {

    /**
     * 当前机器的CPU核数
     */
    private static final Integer CORE_NUM = Runtime.getRuntime().availableProcessors();

    /**
     * 自定义线程池
     */
    private static ExecutorService executorService =  new ThreadPoolExecutor(3,CORE_NUM+1,0L, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(200));

    /**
     * 获取线程池
     * @return
     */
    public static ExecutorService achieveThread() {
//        log.info("CORE_NUM={}",CORE_NUM);
        return executorService;
    }
}
1.1.1 List的循环过程中实现异步执行
package 多线程测试;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * @author
 * @desc List 循环中过滤 开启线程
 * @date
 */
public class ThreadMapCycle {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("yuepengcheng");
        list.add("xingjie");
        list.add("goujian");
        list.add("yueyun");
        list.add("积极上进");
        List<List<String>> partition = Lists.partition(list,2);  //
        System.out.println(partition);  // [[yuepengcheng,xingjie],[goujian,yueyun],[积极上进]]
        List<CompletableFuture<List<String>>> futures = partition.stream().map(new Function<List<String>, CompletableFuture<List<String>>>() {
            @Override
            public CompletableFuture<List<String>> apply(List<String> strings) {
                return CompletableFuture.supplyAsync(new Supplier<List<String>>() {
                    //get方法返回的是List<String> 泛型就是这个
                    @Override
                    public List<String> get() {
                        return null;
                    }
                });
            }
        }).collect(Collectors.toList());

        CompletableFuture<List<String>> future = futures.get(0);  //第一个list [yuepengcheng,xingjie]做的变形
        CompletableFuture<List<String>> future1 = futures.get(1);  // 第二个list  [goujian,yueyun]

    }
}

2 new Thread来异步执行任务(无返回值)

package 多线程测试;

/**
 * @author
 * @desc new Thread重写run方法实现异步线程
 * @date
 */
public class NewThread {

    public void test() {
        //其他处理逻辑

        Thread thread = new Thread() {
            @Override
            public void run() {
                //线程内执行的任务
            }
        };
        //主线程其他处理逻辑

    }
}

3 spring的异步注解@Async实现异步线程

创建异步线程类 使用@Async注解修饰方法

package com.sinog.front.asynctask;

import com.sinog.core.domain.InterfaceLog;
import com.sinog.core.domain.JieKouLog;
import com.sinog.front.feign.biz.api.LogInsertService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @desc 接口日志异步插入省级日志表和部级日志表
 * @author ypc
 * @date 2022/10/20
 */
@Slf4j
@Component
public class AsyncTaskLog {

    @Autowired
    private LogInsertService logInsertService;

    /**
     * 异步执行插入省级日志表数据
     * @param interfaceLog 省级日志表实体类
     */
    @Async("taskAsync01-")
    public void asyncInsertSjLog(InterfaceLog interfaceLog){
        log.info(Thread.currentThread().getName());
        logInsertService.insertLog(interfaceLog);
    }

    /**
     * 异步执行插入部级日志表数据
     * @param jieKouLog sfb接口对接日志实体类
     */
    @Async("taskAsync01-")
    public void asyncInsertbjLog(JieKouLog jieKouLog){
        log.info(Thread.currentThread().getName());
        logInsertService.insertbuLog(jieKouLog);
    }
}

不影响主线程结束 前端页面可以继续操作 异步线程来执行保存动作

@RequestMapping(value = "/transmission/api/azbj/savePreArrangedPersonnel", method = RequestMethod.POST, produces = "application/json;charset=utf-8;")
    public Result savePreArrangedPersonnel(@RequestBody String data) {
		//其他处理逻辑
		try{
			//其他处理逻辑
		 }catch(){
			.....
		 }finally{
			//最终要执行的逻辑
			//异步执行2个方法(动作)
            asyncTask.asyncInsertSjLog(interfaceLog);
            asyncTask.asyncInsertbjLog(jieKouLog);
          }
}

4 使用线程池的方法实现异步线程

4.1 Executors类实现异步编程

execute方法
public static void main(String[] args) {

        // 使用Executors快速创建一个有2个线程的线程池
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                //同步数据到省级 - 中间库 执行一个比较慢的同步数据的任务
                System.out.println("子线程结束");
            }
        };
        // 无返回值 execute
        executor.execute(runnable);
        System.out.println("保存成功,给前端响应");
    }
submit方法
 public static void main(String[] args) {
        // 创建一个有2个线程的线程池
        ExecutorService executor = Executors.newFixedThreadPool(2);
        //2种写法

        //        executor.submit(new Callable<String>() {
//            @Override
//            public String call() throws Exception {
//                if (StringUtils.equals(dataSyncFashion, "middle")) {
//                    SYNC_INTERFACE.syncSjSqlBySql(finalSqlS, name, finalNativepro, finalPrino, finalTemplate);
//                } else {
//                    log.error(">>>>>系统数据同步方式配置错误,可选值['http','middle']<<<<<");
//                }
//                return "ok";
//            }
//        });
        Callable<String> callable = new Callable<>() {
            @Override
            public String call() throws Exception {
                //处理逻辑
                System.out.println("子线程");
                return "返回的值";
            }
        };
        //executor的submit方法里面传Callable  可获得返回值
        Future<String> submit = executor.submit(callable);
        //主线程逻辑
        System.out.println("主线程继续走");
        String s = "";
        try {
            // 子线程处理不完 主线程会暂停到这里
            s = submit.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        //
        System.out.println("主线程结束得到"+s);
    }

4.2 ThreadPoolTaskExecutor 自定义线程池

ThreadPoolTaskExecutor本身就是一个线程池 – 可自定义 – 可使用submit executor方法

public class Executor2 {

    //ThreadPoolTaskExecutor 静态代码块来初始化一个线程池 也可以使用submit(有返回值) 和 execute方法
    private static final ThreadPoolTaskExecutor EXECUTOR = new ThreadPoolTaskExecutor();
    static {
        EXECUTOR.initialize();
        //核心线程数
        EXECUTOR.setCorePoolSize(50);
        //最大线程数
        EXECUTOR.setMaxPoolSize(100);
        //缓冲队列
        EXECUTOR.setQueueCapacity(500);
        //允许线程的空闲时间
        EXECUTOR.setKeepAliveSeconds(1);
        //线程前缀
        EXECUTOR.setThreadNamePrefix("taskAsync001-");
        //线程策略
        EXECUTOR.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        EXECUTOR.setWaitForTasksToCompleteOnShutdown(true);
        EXECUTOR.setAwaitTerminationSeconds(60);
    }
	//其他方法中可使用这个线程池

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值