• Java启动新线程的几种方式(Runnable、Callable、CompletableFuture)


    一、实现Runnable接口

    public class RunnableDemo implements Runnable {
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("in runnable demo");
        }
    }

    非阻塞调用

        public static void main(String[] args) throws Exception {
            Thread runnableThread = new Thread(new RunnableDemo());
            runnableThread.start();
            System.out.println("in main");
        }

    输出结果

    in main
    in runnable demo

    可以看到线程的运行没有阻塞当前线程

    阻塞调用

        public static void main(String[] args) throws Exception {
            Thread runnableThread = new Thread(new RunnableDemo());
            runnableThread.start();
            runnableThread.join();
            System.out.println("in main");
        }

    输出结果

    in runnable demo
    in main

    Join会阻塞当前线程,一直等待自定义线程才返回。

    二、实现Callable接口

    在Runnable的例子中,Runnable接口有一个很大的缺陷就是run方法没有返回值定义,主线程无法获取到线程执行的结果。这个时候就需要Callable接口。

    public class CallableDemo implements Callable<CallableDto> {
        public CallableDto call() throws Exception {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("in callable demo");
            return new CallableDto(1);
        }
    }
    
    class CallableDto {
        private int id;
    
        public CallableDto(int id) {
            this.id = id;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    }

    非阻塞调用

       public static void main(String[] args) throws Exception {
            ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
            Future<CallableDto> future = executor.submit(new CallableDemo());
            System.out.println("in main");
        }

    输出结果,如下所示,新启动的线程没有阻塞当前线程

    in main
    in callable demo

    阻塞调用,且拿到结果

        public static void main(String[] args) throws Exception {
            ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
            Future<CallableDto> future = executor.submit(new CallableDemo());
            CallableDto callableDto = future.get();
            System.out.println("in main");
            System.out.println("id from callable is " + callableDto.getId());
        }

    get方法首先会阻塞主线程,等待当前线程执行结束才返回,且返回线程的执行结果。

    三、CompletableFuture方式

    CompletableFuture是jdk1.8引入的api,做了进一步的封装,用户线程无需实现Callable接口也能启动,且能够返回用户线程的执行结果

    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) 

    一个没有实现Callable的普通方法

    public class CompletableFutureDemo {
        public CompletableFutureDemoDto action() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("in CompletableFutureDemo ");
            return new CompletableFutureDemoDto(1);
        }
    }
    
    class CompletableFutureDemoDto {
        private int id;
    
        public CompletableFutureDemoDto(int id) {
            this.id = id;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    }

    非阻塞调用

        public static void main(String[] args) throws Exception {
            ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
            CompletableFuture<CompletableFutureDemoDto> future = CompletableFuture.supplyAsync(() ->
            {
                return new CompletableFutureDemo().action();
            }, executor);
            System.out.println("in main");
        }

    执行结果,可以看到,主线程没有被阻塞

    in main
    in CompletableFutureDemo 

    阻塞调用且获取结果

        public static void main(String[] args) throws Exception {
            ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
            CompletableFuture<CompletableFutureDemoDto> future = CompletableFuture.supplyAsync(() ->
            {
                return new CompletableFutureDemo().action();
            }, executor);
            CompletableFutureDemoDto demoDto=future.join();
            System.out.println("in main");
            System.out.println("id from demoDto is " + demoDto.getId());
        }

    执行结果,主线程一直被阻塞,一直等到用户线程返回

    in CompletableFutureDemo 
    in main
    id from demoDto is 1
  • 相关阅读:
    让mysql查询强制走索引
    【转】起始时间和终止时间,循环输出每天
    【转】31个实用的find命令
    Hive数据倾斜解决办法总结
    网站架构之可扩展性
    网站架构之高可用性
    网站架构之可伸缩性
    kafka中的消费组
    MySQL知识点小结
    [数据挖掘]用户画像
  • 原文地址:https://www.cnblogs.com/Brake/p/13256469.html
Copyright © 2020-2023  润新知