java使用线程池执行任务

① java一般是如何定义一个线程池的?请看代码

private static ExecutorService taskPool = new ThreadPoolExecutor(16, 32
,200L,TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1000)
			,new ThreadFactoryBuilder()
.setNameFormat("thread-自定义线程名-runner-%d").build());

注:这里的线程池中的参数后续会做介绍 ,你只需要知道 16是核心线程数、32是最大线程数即可。

② 那如何往线程池中加入任务呢?请看代码

public static void main(String[] args) {
        taskPool.submit(new Runnable() {
            @Override
            public void run() {
                // 你要在线程池中执行的代码...
            }
        });
    }

submit方法中传入一个 Runnable对象即可, 是不是很简单,但是一般不是直接new 一个Runnable丢进线程池的,而是写一个类 ,去实现 Runnable,代码如下:

public class ATask implements Runnable {
    
    private String a;

    public ATask(String a) {
        this.a = a;
    }

    public ATask() {}

    @Override
    public void run() {
        // 写下你要在线程池中执行的代码...
        System.out.println("a=" + a);
    }
}

还没完 我经常需要在任务里面注入spring中的service 一般怎么处理呢?

来看代码 ,目标是把AService注入到ATask中并且调用它:

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

class B {
    private static ExecutorService taskPool = new ThreadPoolExecutor(16,32,200L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(1000),
            new ThreadFactoryBuilder().setNameFormat("thread-thirdPushMsgJob-runner-%d").build());
    // ① 在调用线程池之前注入AService到当前类
    @Autowired
    private AService aService;

    public static void main(String[] args) {
        // ② 将AService传入ATask中
        ATask aTask = new ATask("aStr", aService);
        
        // 任务提交到线程池
        taskPool.submit(aTask);
    }
}

public class ATask implements Runnable {

    private String a;
    private AService aService;

    // ③ 对应的ATask需要一个包含 AService的构造函数
    public ATask(String a, AService aService) {
        this.a = a;
        this.aService = aService;
    }

    public ATask() {}

    @Override
    public void run() {
        // 写下你要在线程池中执行的代码...

        // ④ 执行AService中的a()方法
        aService.a();
    }
}

注:上述线程池不能说是完美,但是也符合大多数使用场景了,但如果我想要获取线程池任务的处理结果怎么办呢?

③ 获取线程池的处理结果

  3.1 首先多线程的任务不能再是实现 Runnable,而是实现Callable<T>,因为Callable才允许线程任务返回结果,我们来看代码:

// ① 实现Callable接口 【接口泛型即为线程的返回类型】
public class ATask implements Callable<Object> {

    private String a;

    public ATask(String a) {
        this.a = a;
    }

    public ATask() {}

    @Override
    public Object call() throws Exception {

        // ② 你要在线程池中执行的代码...

        return "你线程任务的返回值";
    }
}

注:可以看到 ATask得call方法已经有返回值了 那怎么获取这个返回值呢

  3.2 获取线程得返回值

class B {
    private static ExecutorService taskPool = new ThreadPoolExecutor(16,32,200L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(1000),
            new ThreadFactoryBuilder().setNameFormat("thread-thirdPushMsgJob-runner-%d").build());

    public static void main(String[] args) throws 
ExecutionException, InterruptedException {
        ATask aTask = new ATask("aStr");

        // 任务提交到线程池
        Future<Object> future = taskPool.submit(aTask);
        // 获取任务返回结果
        Object result = future.get();
        System.out.println(result);
    }
}

只需要接收submit方法的返回值 再get即可获取数据,需要注意的是  future.get()有可能出现异常,建议try-catch处理 future.get(),防止未知异常的出现导致线程任务未正确返回结果

④ 线程池的参数怎么调优?

来看看线程池中参数的释义:

那这些线程池参数都啥意思呢?我们来看

  1. 核心线程数:有任务来了,判断到当前任务数量小于核心线程数时,就新建一个线程而不是把任务放入队列

  2.最大线程数和任务队列:有任务来了,判断当前任务大于核心线程数时,就会往队列里面存放任务,只有当任务队列满了,才会创建新的线程来处理任务,但是线程池最多能有多少个任务是由最大线程数来决定的。 那在这里问问,最大线程数和任务队列都满了怎么破呢? 有个 线程池饱和策略 建议大家去搜索看,网上有很多讲的很好,我就不详讲了。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值