并发编程 -- 创建线程的四种方式

一、继承Thread类

public class ThreadTest {
    public static void main(String[] args) throws Exception {
         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().getId());
	        int i = 10 / 2;
	        System.out.println("运行结果:" + i);
	    }
	}
}

二、实现Runnable接口

public class ThreadTest {
    public static void main(String[] args) throws Exception {
         Runable01 runable01 = new Runable01();
         new Thread(runable01).start();
    }
    
    public static class Runable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
        }
    }
}

三、实现Callable接口

public class ThreadTest {
    public static void main(String[] args) throws Exception {
         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
         new Thread(futureTask).start();
         System.out.println(futureTask.get());
    }
    
    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;
        }
    }
}

四、线程池方式

4.1 Executors工具类

public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
         service.execute(new Runable01());
         Future<Integer> submit = service.submit(new Callable01());
         submit.get();
	}
	
    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;
        }
    }
}
4.1.1 常见的四种线程池
  1. newCachedThreadPool
    参数:核心线程数是0,最大线程数为Integer最大值
    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无法回收,则新建线程。
  2. newFixedThreadPool(int nThreads)
    参数:核心线程数是nThreads,最大线程数也是nThreads,存活时间是0L一直存活
    创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  3. newScheduledThreadPool(int corePoolSize)
    参数:
    创建一个定长线程池,支持定时及周期性执行任务。
  4. newSingleThreadExecutor
    参数:核心线程数是1,最大线程数也是1,存活时间是0L一直存活,队列是无界队列
    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

4.2 ThreadPoolExecutor原生方式

4.2.1 线程池七大参数

(1)corePoolSize
默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出。
(2)maximumPoolSize
当线程数大于或等于核心线程,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize。如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常。
(3)keepAliveTime
当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。
(4)unit - {keepAliveTime}参数的时间单位。
(5)workQueue - 一个阻塞队列,用来存储等待执行的任务。
(6)threadFactory - 执行器创建新线程时要使用的工厂。
(7)handler - 表示当拒绝处理任务时的策略。

4.2.2 执行任务逻辑

在这里插入图片描述
(1)判断核心线程数是否已满,核心线程数大小和corePoolSize参数有关,未满则创建线程执行任务.
(2)若核心线程池已满,判断队列是否满,队列是否满和workQueue参数有关,若未满则加入队列中。
(3)若队列已满,判断线程池是否已满,线程池是否已满和maximumPoolSize参数有关,若未满创建线程执行任务。
(4)若线程池已满,则采用拒绝策略处理无法执执行的任务,拒绝策略和handler参数有关。

4.2.3 拒绝策略

(1)CallerRunsPolicy:由调用线程处理该任务
(2)AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常
(3)DiscardPolicy:丢弃任务,但是不抛出异常。
(4)DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务。

五、CompletableFuture异步编排

5.1 应用场景

复杂业务逻辑查询,需要异步且相互之间有关系,某些任务需要其他任务返回结果(类似于vue调用ajax请求,需要某些ajax请求时,then)

5.2 基本使用

5.2.1 简单体验
public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
        /**
         * 创建异步对象
         * runAsync:无返回值
         * supplyAsync:有返回值
         */
         CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
             System.out.println("当前线程:" + Thread.currentThread().getId());
             int i = 10 / 2;
             System.out.println("运行结果:" + i);
         }, executor);

        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor);
        System.out.println("future2.get() = " + future2.get());
	}
}
5.2.2 whenComplete 方法完成后的感知(但是无法修改返回数据)
public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
        /**
         * whenComplete
         * 方法完成后的感知
         */
         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
             System.out.println("当前线程:" + Thread.currentThread().getId());
             int i = 10 / 0;
             System.out.println("运行结果:" + i);
             return i;
         }, executor).whenComplete((res,exception) -> {
             //虽然能得到异常信息,但是没法修改返回数据
             System.out.println("异步任务成功完成了...结果是:" + res + "异常是:" + exception);
         }).exceptionally(throwable -> {
             //可以感知异常,同时返回默认值
             return 10;
         });
        Integer integer = future.get();
        System.out.println("integer = " + integer);
    }
}
5.2.3 handle 方法执行完后的处理
public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
        /**
         * handle
         * 方法执行完后的处理
         */
         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
             System.out.println("当前线程:" + Thread.currentThread().getId());
             int i = 10 / 2;
             System.out.println("运行结果:" + i);
             return i;
         }, executor).handle((result,thr) -> {
             if (result != null) {
                 return result * 2;
             }
             if (thr != null) {
                 System.out.println("异步任务成功完成了...结果是:" + result + "异常是:" + thr);
                 return 0;
             }
             return 0;
         });
        System.out.println("future.get() = " + future.get());
    }
}
5.2.4 线程串行化
public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
        /**
         * 线程串行化
         * 1、thenRunAsync:不能获取上一步的执行结果
         * 2、thenAcceptAsync:能接受上一步结果,但是无返回值
         * 3、thenApplyAsync:能接受上一步结果,有返回值
         *
         */
        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).thenRunAsync(() -> {
            System.out.println("任务2启动了...");
        }, executor);

        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).thenAcceptAsync(res -> {
            System.out.println("任务2启动了..." + res);
        }, executor);

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了..." + res);
            return "Hello" + res;
        }, executor);
        System.out.println("main......end....." + future.get());
    }
}

5.2 两任务组合(都要完成)

public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
        /**
         * 两任务组合:都要完成
         * runAfterBoth:获取不到前面两个任务的结果
         * thenAcceptBothAsync:能获取到前面两个任务的结果,没有返回值
         * thenCombineAsync:能获取到前面两个任务的结果,有返回值
         */
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            System.out.println("任务2结束:");
            return "Hello";
        }, executor);
//        future01.runAfterBothAsync(future02, () -> {
//            System.out.println("任务3开始。。。");
//        } ,executor);
//        future01.thenAcceptBothAsync(future02, (f1, f2) -> {
//            System.out.println("任务3开始。。。之前的结果:" + f1 + "-->" + f2);
//        } , executor);
        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + " : " + f2 + " -> Hah..";
        }, executor);
        System.out.println("future.get() = " + future.get());
	}
}

5.3 两任务组合(一个完成)

public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
        /**
         * 两任务组合:一个完成
         * runAfterEitherAsync:任意一个任务完成后,获取不到它的结果,没有返回值
         * acceptEither:任意一个任务完成后,能获取到它的结果,没有返回值
         * applyToEither:任意一个任务完成后,能获取到它的结果,有返回值
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            System.out.println("任务2结束:");
            return "Hello";
        }, executor);
//        future01.runAfterEitherAsync(future02, () -> {
//            System.out.println("任务3开始。。。");
//        }, executor);
//        future01.acceptEitherAsync(future02, (res) -> {
//            System.out.println("任务3开始。。。" + res);
//        } , executor);
        CompletableFuture<String> future = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("任务3开始。。。获取到的res:" + res);
            return "当前任务的res:" + res + "...hello...";
        }, executor);
        System.out.println("future.get() = " + future.get());
	}
}

5.4 多任务组合

public class ThreadTest {

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

    public static void main(String[] args) throws Exception {
        /**
         * 多任务组合
         * allOf:等待所有任务完成
         * anyOf:只要有一个任务完成
         */
        CompletableFuture<String> futureImage = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "hello.jpg";
        }, executor);
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256G";
        }, executor);
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询商品介绍");
            return "华为";
        }, executor);
//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImage, futureAttr, futureDesc);
//        allOf.get();// 等待所有结果完成
//        System.out.println("获取结果:" + futureImage.get() + " : " + futureAttr.get() + " : " + futureDesc.get());
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImage, futureAttr, futureDesc);
        anyOf.get();// 等待任意一个结果完成
        System.out.println("获取结果:" + anyOf.get());
        System.out.println("main...end...");
        // 打印疑问:因为使用线程池,所以所有任务都会执行完成
	}
}

5.5 实际多任务组合业务代码

说明:因为future01的结果其他的线程需要使用,所以使用CompletableFuture.supplyAsync(),future02需要使用future01的结果所以使用thenAcceptAsync,future03同理。因为future04的结果其他的线程不需要使用,所以使用CompletableFuture.runAsync()。CompletableFuture.allOf(future01,future02,future03,future04).get();等待所有的线程任务完成,主线程继续执行。

		CompletableFuture<SkuInfoEntity> future01 =CompletableFuture.supplyAsync(() ->{
            //业务逻辑res=xxx;
            return res;
        }, executor);

        CompletableFuture<Void> future02 = future01.thenAcceptAsync((res) -> {        
            // 业务逻辑res.getXxx()
        }, executor);

        CompletableFuture<Void> future03 = future01.thenAcceptAsync((res) -> {
            // 业务逻辑res.getXxx()
        }, executor);

        CompletableFuture<Void> future04 = CompletableFuture.runAsync(() -> {
            // 业务逻辑
        }, executor);

        //等到所有任务都完成
		CompletableFuture.allOf(future01,future02,future03,future04).get();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值