Java线程池-异步任务编排

1.初始化线程的4 种方式

1.继承 Thread

package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class MytestApplicationTests {


    @Test
    public void test() {

        Thread1 thread1 = new Thread1();
        thread1.run();
    }

    /**
     * 继承Thread接口
     */
    public class Thread1 extends Thread{

        @Override
        public void run() {
            System.out.println("thread1运行开始");
            try {
                Thread.sleep(5000);//单位毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread1运行结束");
        }
    }

}

Java线程池-异步任务编排_第1张图片

2.实现 Runnable 接口

package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class MytestApplicationTests {

    @Test
    public void test() {

        Thread2 thread2 = new Thread2();
        thread2.run();
    }
    

    /**
     * 实现Runnable接口
     */
    public class Thread2 implements Runnable{

        @Override
        public void run() {
            System.out.println("thread2运行开始");
            try {
                Thread.sleep(5000);//单位毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread2运行结束");
        }
    }
}

Java线程池-异步任务编排_第2张图片

3.实现 Callable 接口

FutureTask可以拿到返回结果,可以处理异常
futureTask.get()阻塞等待整个线程执行完成,获取返回结果

package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

@SpringBootTest
public class MytestApplicationTests {

    @Test
    public void test() throws ExecutionException, InterruptedException {

        Callable01 callable01 = new Callable01();
        FutureTask<Integer> futureTask = new FutureTask<>(callable01);

        Thread thread = new Thread(futureTask);
        thread.start(); //启动线程
        Integer integer = futureTask.get();//等待线程返回结果之前, 下面的代码不会执行
        System.out.println(integer);
        System.out.println("任务完成");
    }



    /**
     *  实现Callable接口
     */
    public class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("thread3运行开始");
            try {
                Thread.sleep(5000);//单位毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread3运行结束");
            return 10;
        }
    }
}

Java线程池-异步任务编排_第3张图片

4.线程池ExecutorService

package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.*;

@SpringBootTest
public class MytestApplicationTests {

    @Test
    public void test() throws ExecutionException, InterruptedException {
        Callable01 callable01 = new Callable01();

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        FutureTask<Integer> futureTask = (FutureTask<Integer>)executorService.submit(callable01);
        System.out.println("等待结果");
        System.out.println(futureTask.get());
        System.out.println("任务完成");
    }


    /**
     *  实现Callable接口
     */
    public class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("thread3运行开始");
            try {
                Thread.sleep(5000);//单位毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread3运行结束");
            return 10;
        }
    }

}

Java线程池-异步任务编排_第4张图片

2.线程池的7大参数

线程池工作流程图
Java线程池-异步任务编排_第5张图片

Java线程池-异步任务编排_第6张图片

  • corePoolSize(必需):核心线程数。默认情况下,核心线程会一直存活,但是当将
    allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。

  • maximumPoolSize(必需):线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。

  • keepAliveTime(必需):线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。

  • unit(必需):指定 keepAliveTime参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)。

  • workQueue(必需):任务队列。通过线程池的 execute() 方法提交的 Runnable对象将存储在该参数中。其采用阻塞队列实现。

  • threadFactory(可选):线程工厂。用于指定为线程池创建新线程的方式。

  • handler(可选):拒绝策略。当达到最大线程数时需要执行的饱和策略。

一个线程池 core 7; max 20 ,queue:50,100 并发进来怎么分配的?
先有 7 个能直接得到执行,接下来 50 个进入队列排队,在多开 13 个继续执行。现在 70 个 被安排上了。剩下 30 个默认拒绝策略。

3.常见的4 种线程池

  • newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若 无可回收,则新建线程。

  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  • newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

  • newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行

4.CompletableFuture 异步编排

1.创建异步对象

CompletableFuture 提供了四个静态方法来创建一个异步操作。
Java线程池-异步任务编排_第7张图片
1、runAsync都是没有返回结果的,supplyAsync都是可以获取返回结果的
2、可以传入自定义的线程池,否则就用默认的线程池;

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //异步任务1
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("运行结果1:" + i);
        }, executor);

        //异步任务2
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 2;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("运行结果2:" + i);
            return i;
        }, executor);

        Integer res2 = (Integer) future2.get();
        System.out.println("res2="+res2);
    }

}

Java线程池-异步任务编排_第8张图片

2.计算完成时回调方法

Java线程池-异步任务编排_第9张图片

  • whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
  • whenComplete 和 whenCompleteAsync 的区别:
    whenComplete:是执行当前任务的线程执行继续执行whenComplete 的任务。 whenCompleteAsync:是执行把 whenCompleteAsync这个任务继续提交给线程池 来进行执行。
  • 方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程
    执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)

1.在 supplyAsync、runAsync执行完毕后还想做其他任务就可以使用链式调用whenComplete(是指当前任务的线程执行继续执行)、whenCompleteAsync(是重新提交到线程池进行执行),这两个可以接收到成功值或者异常信息,只能作为监听成功或失败。

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            return "ok";
        }, executor).whenComplete((res,exception)->{
            System.out.println("结果是:"+res+"异常是:"+exception);
        });
        String res = future.get();
        System.out.println("线程返回结果:"+res);

    }

}

Java线程池-异步任务编排_第10张图片
2.还可以链式调用exceptionally,可以获取到异常信息并且可以修改最终值.

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            int i = 10/0; //模拟异常
            return "ok";
        }, executor).whenComplete((res,exception)->{
            System.out.println("结果是:"+res+"异常是:"+exception);
        }).exceptionally((exception)->{
            return "not ok";
        });
        String res = future.get();
        System.out.println("线程返回结果:"+res);

    }
}

Java线程池-异步任务编排_第11张图片

3.handle 方法

handle方法可以接受两个参数(成功值,异常信息),返回一个参数(可以修改最终返回值),相当于方法执行后的处理

package com.atguigu.gulimall.mytest.test;

import io.swagger.models.auth.In;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            //int i = 10/0; //模拟异常
            return "ok";
        }, executor).handle((res, exception) -> {
            if (exception==null){
                System.out.println("结果是:" + res);
                return res;
            }else{
                System.out.println("异常是:" + exception);
                return "not ok";
            }
        });

        String res = future.get();
        System.out.println("线程返回结果:"+res);

    }
}

Java线程池-异步任务编排_第12张图片

5.线程串行化方法

Java线程池-异步任务编排_第13张图片
提示: 链式调用方法后不加Async是指当前任务的线程执行继续执行,加上Async是重新提交到线程池进行执行

1.thenRun、thenRunAsync

要上面的任务执行完毕后才开始执行此方法的后续操作,无返回结果。

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture future = CompletableFuture.supplyAsync(() -> {
            System.out.println("one");
            return "ok";
        },executor).thenRunAsync(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("执行后续操作。。。");
        },executor);
    }
}

Java线程池-异步任务编排_第14张图片

2.thenAccept、thenAcceptAsync

有一个入参(消费处理结果),接收处理结果进行后续操作,无返回结果。

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture future = CompletableFuture.supplyAsync(() -> {
            System.out.println("one");
            return "ok";
        }, executor).thenAcceptAsync((res)->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("接收到结果:"+res+"执行后续操作。。。");
        },executor);
    }
}

Java线程池-异步任务编排_第15张图片

3.thenApply、thenApplyAsync

接收返回结果,并进行后续操作,并返回当前任务的返回值

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            return "ok";
        }, executor).thenApplyAsync((res)->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("接收到结果:"+res+"执行后续操作。。。");
            return "ok666";
        },executor);

        String res = future.get();
        System.out.println("线程返回结果:"+res);

    }
}

Java线程池-异步任务编排_第16张图片

4.两任务组合 - 都要完成

Java线程池-异步任务编排_第17张图片

两个任务必须都完成,触发该任务。

1.thenCombine、thenCombineAsync:组合两个futre的返回结果,并且返回当前任务的返回值

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return 10;
        }, executor);
        CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行完毕");
            return 20;
        }, executor);
        CompletableFuture<Integer> combineAsync = supplyAsync1.thenCombineAsync(supplyAsync2, (res1, res2) -> {
            System.out.println("结合任务1和任务2的结果计算出任务3,并返回");
            return res1+res2;
        }, executor);
        Integer res = combineAsync.get();
        System.out.println("结果:"+res);
    }
}

Java线程池-异步任务编排_第18张图片

2.thenAcceptBoth、thenAcceptBothAsync:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有返回值。

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return 10;
        }, executor);
        CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行完毕");
            return 20;
        }, executor);
        CompletableFuture<Void> acceptBothAsync = supplyAsync1.thenAcceptBothAsync(supplyAsync2, (res1, res2) -> {
            System.out.println("结合任务1和任务2的结果执行任务3,没有返回值!");
            System.out.println("res1+res2="+(res1+res2));
        }, executor);
    }
}

Java线程池-异步任务编排_第19张图片

3.runAfterBoth、thenAfterBothAsync:组合两个futre,不需要返回结果,只需要处理两个Future后执行该任务。

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return 10;
        }, executor);
        CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行完毕");
            return 20;
        }, executor);

        CompletableFuture<Void> afterBothAsync = supplyAsync1.runAfterBothAsync(supplyAsync2, () -> {
            System.out.println("任务1和任务2执行完执行任务3.没有返回值!");
        }, executor);
    }
}

Java线程池-异步任务编排_第20张图片

5.两任务组合 - 一个完成

Java线程池-异步任务编排_第21张图片
1.applyToEitherAsync、applyToEither: 两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return 10;
        }, executor);
        CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行完毕");
            return 20;
        }, executor);

        supplyAsync1.applyToEitherAsync(supplyAsync2,(res)->{
            System.out.println("res="+res);
            System.out.println("只要有一个完成就接收值,处理并返回值!");
            return 3;
        },executor);
    }
}

Java线程池-异步任务编排_第22张图片
2.acceptEitherAsync、acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。

supplyAsync1.acceptEitherAsync(supplyAsync2,(res)->{
            System.out.println("只要有一个完成就接收值,处理不能返回值!");
        },executor);

3.runAfterEitherAsync、runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返回值。

supplyAsync1.runAfterEitherAsync(supplyAsync2,()->{
            System.out.println("只要有一个完成不接受值,处直接理不能返回值!");
        },executor);

6.多任务组合

在这里插入图片描述

1.allOf:等待所有任务完成,没有返回值

package com.atguigu.gulimall.mytest.test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return 10;
        }, executor);
        CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2执行完毕");
            return 20;
        }, executor);

        CompletableFuture<Integer> supplyAsync3 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务3执行完毕");
            return 30;
        }, executor);

        CompletableFuture<Void> all = CompletableFuture.allOf(supplyAsync1, supplyAsync2, supplyAsync3);
        System.out.println("ok1");
        all.get(); //阻塞,等待所有任务完成才执行后续代码
        System.out.println("ok2");

    }
}

Java线程池-异步任务编排_第23张图片

2.anyOf:只要有一个任务完成, 可以有返回值

package com.atguigu.gulimall.mytest.test;


import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

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

        CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1执行完毕");
            return 10;
        }, executor);
        CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2执行完毕");
            return 20;
        }, executor);

        CompletableFuture<Integer> supplyAsync3 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务3执行完毕");
            return 30;
        }, executor);

        CompletableFuture<Object> all = CompletableFuture.anyOf(supplyAsync1, supplyAsync2, supplyAsync3);
        System.out.println("ok1");
        Integer res = (Integer) all.get(); //阻塞,等待有一个任务完成才执行后续代码
        System.out.println("res="+res);
        System.out.println("ok2");

    }
}

Java线程池-异步任务编排_第24张图片

你可能感兴趣的:(Java基础,java,jvm,开发语言)