异步、多线程

173 阅读10分钟

异步&多线程

多线程

多线程创建的几种方式

  1. 继承Thread
public class Test {
    public static void main(String[] args) {
        System.out.println("main方法...start");
        Thread thread = new Thread01();
        thread.start();
        System.out.println("main方法...end");
    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
        }
    }
}
  1. 实现Runnable接口
public class Test {
    public static void main(String[] args) {
        System.out.println("main方法...start");
        Runnable01 runnable01 = new Runnable01();
        Thread thread = new Thread(runnable01);
        thread.start();
        System.out.println("main方法...end");
    }

    public static class Runnable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
        }
    }
}
  1. 实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常)
public class Test {
    public static void main(String[] args) {
        System.out.println("main方法...start");
        FutureTask<Object> futureTask = new FutureTask<>(new Callable01());
        Thread thread = new Thread(futureTask);
        thread.start();
        Object o = null;
        try {
            //阻塞等待 等待整个线程执行完成,获取返回结果
            o = futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        //需要等待获取到返回结果才会进行打印
        System.out.println("main方法...end==>" + o);
    }

    /**
     * Callable<Object> ==>Object对应需要返回的结果
     */
    public static class Callable01 implements Callable<Object> {
        @Override
        public Object call() throws Exception {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }
    }
}
  1. 线程池(推荐使用) 以上三种方式创建线程不推荐使用,如果多个请求每次new Thread();可能会导致我们资源耗尽;我们应该将所有的异步线程任务交给线程池执行
/**
* 根据Executors来创建线程池
*/
public class Test {
    /**
     * 当前系统中池的数量应该只会有一两个(根据自己的业务场景来定);每个异步任务,提交给线程池让它自己去执行
     * Executors.newFixedThreadPool(10) 获取一个定长线程池
     */
    public static ExecutorService executor = Executors.newFixedThreadPool(10);
    
    /**
     * 七个参数
     * int corePoolSize :核心线程数【一直存在,除非设置allowCoreThreadTimeOut】,线程池创建好之后就准备就绪的线程数量,就等待来接收异步线程任务去执行
     * int maximumPoolSize :最大线程数;控制资源(CPU密集型[CPU核数+1]、IO密集型[CPU核数*2、CPU核数/(1-阻塞系数[0.8~0.9])])
     * long keepAliveTime : 存活时间(如果当前线程数量大于核心数量,释放空闲线程[maximumPoolSize-corePoolSize]需要的时间)
     * TimeUnit unit : 时间单位
     * BlockingQueue<Runnable> workQueue : 阻塞队列。如果任务有很多,就会将目前对的任务放在队列,只要有线程空闲了,就会从队列中取出新的任务继续执行
     * ThreadFactory threadFactory : 线程创建工厂
     * RejectedExecutionHandler handler : 如果队列满了,按照我们指定的拒绝策略拒绝执行任务(new AbortPolicy()[默认,直接抛出异常阻止系统正常运行]、new DiscardPolicy()[直接丢弃进来的任务]、new DiscardOldestPolicy()[丢弃等待最久的任务]、new CallerRunsPolicy()[不抛弃任务,也不丢弃任务,将任务回退给调用者])
     * <p>
     * 执行顺序:
     * 1.线程池创建好,准备core数量的核心线程,准备接收任务
     * 2.如果核心线程数满了,再进来的任务就放入阻塞队列,空闲的线程就自己会去阻塞队列里面获取任务执行
     * 3.阻塞队列如果也满了,就会直接开新线程执行,最大开到max指定的数量
     * 4.如果max满了,就会使用拒绝策略拒绝任务
     * 5.max没满都执行完了,有很多空闲线程;就会在指定的时间(keepAliveTime)以后释放maximumPoolSize-corePoolSize这些线程
     * <p>
     * 提示:
     * new LinkedBlockingDeque<>() 默认是Integer.MAX_VALUE。可能导致内存不够 需要根据压测结果自己指定
     */
    public static ThreadPoolExecutor executor01 = new ThreadPoolExecutor(10
            , 200
            , 10
            , TimeUnit.SECONDS
            , new LinkedBlockingDeque<>()
            , Executors.defaultThreadFactory()
            , new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        System.out.println("main方法...start");
//        executor.execute(); //无法获取任务返回值
        Future<Object> submit = executor.submit(new Callable01());//可以获取任务返回值
        Object o = null;
        try {
            o = submit.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("main方法...end == >" + o);
    }

    /**
     * Callable<Object> ==>Object对应需要返回的结果
     */
    public static class Callable01 implements Callable<Object> {
        @Override
        public Object call() throws Exception {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }
    }
}

线程池几种类型

  • Executors.newCachedThreadPool(); //可缓存的线程池 core是0,所有都可以回收
  • Executors.newFixedThreadPool(10); //定长线程池,固定大小不可回收
  • Executors.newSingleThreadExecutor(); // core是1 单线程池
  • Executors.newScheduledThreadPool(10);//定时任务线程池
    区别
  • 第1、2两种方式不能获取返回值,第3种可以获取返回值
  • 第1、2、3种方式不能进行资源控制
  • 第4种可以进行资源控制,性能稳定
    优点
  • 降低资源消耗
  • 提供响应速度
  • 提供线程的可管理性

CompletableFuture异步编排

创建异步对象

提供了四个静态方法创建异步操作

  • public static CompletableFuture runAsync(Runnable runnable) //无返回值
  • public static CompletableFuture runAsync(Runnable runnable,Executor executor) //无返回值,可传入自定义的线程池对象
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture.runAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
        }, executor);
        System.out.println("main方法...end");
    }

}
  • public static CompletableFuture supplyAsync(Supplier supplier)//有返回值
  • public static CompletableFuture supplyAsync(Supplier supplier,Executor executor)//返回值,可传入自定义的线程池对象
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }, executor);
        Integer integer = 0;
        try {
            integer = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("main方法...end" + integer);
    }

}

异步完成回调与异常感知

whenComplete只可以进行感知结果和异常,但是无法对结果进行修改

  • public CompletableFuture whenComplete(BiConsumer<? super T, ? super Throwable> action) 执行当前任务的线程继续执行
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }, executor).whenComplete((res, exception) -> {
            System.out.println("结果是-->" + res + "异常是-->" + exception);
        });
        Integer integer = 0;
        try {
            integer = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("main方法...end" + integer);
    }

}
  • public CompletableFuture whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action) 继续提交给线程池进行处理
  • public CompletableFuture whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor) 继续提交给线程池进行处理,指定自定义线程池
  • public CompletableFuture exceptionally(Function<Throwable, ? extends T> fn) 处理异常情况
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 0;
            System.out.println("运行结果---" + num);
            return num;
        }, executor).whenComplete((res, exception) -> {
            System.out.println("结果是-->" + res + "异常是-->" + exception);
        }).exceptionally((exception) -> {
            //可以感知异常,进行设置默认值
            return 10;
        });
        Integer integer = 0;
        try {
            integer = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("main方法...end" + integer);
    }

}

handle可对结果进行后续处理

public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }, executor).handle((res, exception) -> {
            if (res != null) {
                return res * 2;
            }
            if (exception != null) {
                return res;
            }
            return 0;
        });
        Integer integer = 0;
        try {
            integer = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("main方法...end" + integer);
    }

}

线程串行化

  • public CompletableFuture thenRun(Runnable action)
  • public CompletableFuture thenRunAsync(Runnable action)
  • public CompletableFuture thenRunAsync(Runnable action,Executor executor) 不能获取上一步的执行结果,无返回值
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }, executor);


        future.thenRunAsync(() -> {
            System.out.println("任务2启动了....");
        }, executor);

        System.out.println("main方法...end");
    }

}
  • public CompletableFuture thenAccept(Consumer<? super T> action)
  • public CompletableFuture thenAcceptAsync(Consumer<? super T> action)
  • public CompletableFuture thenAcceptAsync(Consumer<? super T> action,Executor executor)能接收上一个线程的执行结果,无返回值
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }, executor);


        future.thenAcceptAsync((res) -> {
            System.out.println("任务2启动了...."+res);
        }, executor);

        System.out.println("main方法...end");
    }

}
  • public CompletableFuture thenApply(Function<? super T,? extends U> fn)
  • public CompletableFuture thenApplyAsync(Function<? super T,? extends U> fn)
  • public CompletableFuture thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) 能接收上一个线程的执行结果,有返回值
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = future.thenApplyAsync((res) -> {
            System.out.println("任务2启动了...." + res);
            return res * 2;
        }, executor);
        Integer integer = 0;
        try {
            integer = future1.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("main方法...end" + integer);
    }

}

两任务组合-都要完成

  • public CompletableFuture runAfterBoth(CompletionStage<?> other,Runnable action)
  • public CompletableFuture runAfterBothAsync(CompletionStage<?> other,Runnable action)
  • public CompletableFuture runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor) 组合两个future,不需要获取future的结果,只需要两个future处理完任务后,处理该任务
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 5;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        future.runAfterBothAsync(future1,()->{
            System.out.println("任务3开始");
        },executor);


        System.out.println("main方法...end");
    }

}
  • public CompletableFuture thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
  • public CompletableFuture thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
  • public CompletableFuture thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,Executor executor) 组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 5;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        future.thenAcceptBothAsync(future1, (res1, res2) -> {
            System.out.println("第一个结果的返回值" + res1 + "第二个结果的返回值" + res2);
        }, executor);


        System.out.println("main方法...end");
    }

}
  • public <U,V> CompletableFuture thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
  • public <U,V> CompletableFuture thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
  • public <U,V> CompletableFuture thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn, Executor executor) 组合两个future,获取两个future的返回结果,并返回当前任务的返回值
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 5;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future2 = future.thenCombineAsync(future1, (res1, res2) -> {
            System.out.println("第一个结果的返回值" + res1 + "第二个结果的返回值" + res2);
            return res1 + res2;
        }, executor);

        Integer integer = 0;
        try {
            integer = future2.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("main方法...end" + integer);
    }

}

两任务组合-单个完成

  • public CompletableFuture runAfterEither(CompletionStage<?> other,Runnable action)
  • public CompletableFuture runAfterEitherAsync(CompletionStage<?> other,Runnable action)
  • public CompletableFuture runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor) 组合两个future,两个任务有一个任务执行完,不需要获取返回结果,处理任务没有新的返回结果
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("当前线程1---" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int num = 10 / 5;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        future.runAfterEitherAsync(future1, () -> {
            System.out.println("任务3开始....");
        }, executor);


        System.out.println("main方法...end");
    }

}
  • public CompletableFuture acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
  • public CompletableFuture acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)
  • public CompletableFuture acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor) 两个任务有一个任务执行完,获取它的返回结果,处理任务没有新的返回结果
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("当前线程1---" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int num = 10 / 5;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        future.acceptEitherAsync(future1, (res) -> {
            System.out.println("任务返回结果" + res);
        }, executor);


        System.out.println("main方法...end");
    }

}
  • public CompletableFuture applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)
  • public CompletableFuture applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)
  • public CompletableFuture applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn,Executor executor) 两个任务有一个任务执行完,获取它的返回结果,处理任务并返回新的返回结果
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("当前线程1---" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int num = 10 / 5;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future2 = future.applyToEitherAsync(future1, (res) -> {
            System.out.println("任务返回结果" + res);
            return res * 2;
        }, executor);

        Integer integer = 0;
        try {
            integer = future2.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        System.out.println("main方法...end" + integer);
    }

}

多任务组合

  • public static CompletableFuture allOf(CompletableFuture<?>... cfs) 等待所有结果完成
public class Test {

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

    public static void main(String[] args) {
        System.out.println("main方法...start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1---" + Thread.currentThread().getName());
            int num = 10 / 2;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("当前线程1---" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int num = 10 / 5;
            System.out.println("运行结果1---" + num);
            return num;
        }, executor);


        CompletableFuture<Void> allOf = CompletableFuture.allOf(future, future1);
        try {
//            allOf.get();
            System.out.println("第一个返回结果" + future.get() + "第二个返回结果" + future1.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }

}
  • public static CompletableFuture anyOf(CompletableFuture<?>... cfs) 一个任务完成即可
    public class Test {
    
        public static ExecutorService executor = Executors.newFixedThreadPool(10);
    
        public static void main(String[] args) {
            System.out.println("main方法...start");
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程1---" + Thread.currentThread().getName());
                int num = 10 / 2;
                System.out.println("运行结果1---" + num);
                return num;
            }, executor);
    
            CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(3000);
                    System.out.println("当前线程2---" + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int num = 10 / 5;
                System.out.println("运行结果2---" + num);
                return num;
            }, executor);
    
    
            CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future, future1);
            try {
                anyOf.get();
                System.out.println("返回结果..."); //此处打印先于  当前线程2---
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
    
        }
    
    }