异步、线程池、以及CompletableFuture 组合式异步编排

Java线程初始化与线程池详解

初始化线程的4种方式

1-继承 Thread
2-实现 Runnable 接口
3-实现 Callable接口 + FutureTask (可以拿到返回结果,可以处理异常)
4-线程池
Executors.newFixedThreadPool(10);
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
 

以上四种方式的区别

  • 方式1和方式2:主进程无法获取线程的运算结果。不适合当前场景

  • 方式3:主进程可以获取线程的运算结果,但是不利于控制服务器中的线程资源。可以导致服务器资源耗尽。

  • 方式4:可以控制资源,系统性能稳定

下面展示下以上实现方式的DEMO代码

public class ThreadTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main...start....");
        /**
         * 1. 继承 Thread
         *      Thread01 thread = new Thread01();
         *      thread.start();
         * 2. 实现 Runnable 接口
         *      Runable01 runable01 = new Runable01();
         *      new Thread(runable01).start();
         * 3. 实现 Callable接口 + FutureTask (可以拿到返回结果,可以处理异常)
         *      FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
         *      new Thread(futureTask).start();
         *      // 阻塞等待整个线程执行完成,获取返回结果
         *      Integer integer = futureTask.get();
         * 4. 线程池
         *      给线程池直接提交任务.
         *      我们以后在业务代码里面,以上三种启动线程的方式都不用。【将所有的多线程异步任务都交给线程池执行】
         * 区别:
         *      1、2不能得到返回值,3可以获取返回值
         *      1、2、3都不能控制资源
         *      4 可以控制资源,系统性能稳定
         */
    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果:" + i);
        }
    }

    public static class Runable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果:" + i);
        }
    }

    public static class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果:" + i);
            return i;
        }
    }


}

一、线程池配置详解以及DEMO

 1-1线程池参数以及解释

 拒绝策略的详解

线程池中的任务队列已满且线程池中的线程数达到 maximumPoolSize 时,无法再提交新的任务。这种情况下,线程池就需要使用拒绝策略来处理这些无法处理的任务。Java 提供了四种默认的拒绝策略,具体如下:

  1. CallerRunsPolicy:当线程池无法处理新任务时,会把任务交给调用线程执行(即当前 execute() 方法所在的线程执行)。可以有效避免任务被丢失,但可能会影响调用线程的性能。

  2. AbortPolicy:当线程池无法处理新任务时,会直接抛出一个 RejectedExecutionException。这是默认的拒绝策略。

  3. DiscardPolicy:当线程池无法处理新任务时,会直接把任务丢弃,不做任何处理。

  4. DiscardOldestPolicy:当线程池无法处理新任务时,会把任务队列中最旧(即最先提交)的任务丢弃,然后重新尝试提交任务。

除了上述四种默认的拒绝策略外,也可以自定义一个拒绝策略。只需要实现 RejectedExecutionHandler 接口,并实现其中的 rejectedExecution() 方法即可。在该方法中,可以定义任何自定义的处理逻辑,比如记录日志、重试等。通过自定义拒绝策略来更好地控制任务的处理方式。

1-2 线程池测试DEMO

/**
 * @Description:
 * @Created: with IntelliJ IDEA.
 * @author: 夏沫止水
 * @createTime: 2020-06-18 11:16
 **/
/**
    1)、继承 Thread
    2)、实现 Runnable 接口
    3)、实现 Callable 接口 + FutureTask (可以拿到返回结果,可以处理异常)
    4)、线程池
 */
public class ThreadTest {


    // 当前系统池只有一两个,每个异步任务直接提交给线程池,让他自己去执行
    public static ExecutorService service = Executors.newFixedThreadPool(10);

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

         service.execute(new Runable01());
         Future<Integer> submit = service.submit(new Callable01());
         submit.get()
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syfjava

请博主喝杯蜜雪冰城

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值