首页 > 其他分享 >多线程之CompletableFuture

多线程之CompletableFuture

时间:2023-02-05 18:11:59浏览次数:36  
标签:异步 java System 线程 println CompletableFuture 多线程

目录

1.Future回顾

Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程,或者使用轮询方式判断 Future.isDone 任务是否结束,再获取结果。

代码示例:

import java.util.concurrent.*;

/**
 * 大汉软件:多线程
 */
public class FutureTest {
    public static void main(String[] args) throws Exception {
        //线程池创建
        ThreadPoolExecutor executors = new ThreadPoolExecutor(5, 10,
                200L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

        Future<Long> future = executors.submit(() -> {
            try {
                Thread.sleep(199);
                return getCurrentTime();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 0L;
        });


        // 获取结果
        System.out.println(future.get());
    }

    public static long getCurrentTime() {
        long nanoTime = System.nanoTime();
        return nanoTime;
    }
}

Future无法解决多个异步任务需要相互依赖的场景(主线程需要等待子线程任务执行完毕之后在进行执行,这个时候需要CountDownLatch

代码如下

import java.util.concurrent.*;

/**
 * 大汉软件:多线程
 */
public class FutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //线程池创建
        ThreadPoolExecutor executors = new ThreadPoolExecutor(5, 10,
                200L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

        CountDownLatch count = new CountDownLatch(2);
        long startTime = System.currentTimeMillis();
        Future<String> future1 = executors.submit(() -> {
            Thread.sleep(180);
            count.countDown();
            return "线程1";
        });

        Future<String> future2 = executors.submit(() -> {
            Thread.sleep(50);
            count.countDown();
            return "线程2";
        });

        count.await();

        //模拟主程序耗时时间
        Thread.sleep(600);
        System.out.println("获取用户信息:" + future1.get());
        System.out.println("获取商品信息:" + future2.get());
        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");
        // 关闭线程池
        executors.shutdown();
    }
}

测试结果:

获取用户信息:线程1
获取商品信息:线程2
总共用时839ms

总共用时 >= 600ms + 180ms。

2.CompletableFuture实现上面示例

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

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        long startTime = System.currentTimeMillis();

        CompletableFuture<String> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
            //模拟耗时180毫秒
            try {
                Thread.sleep(180);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "用户A";
        });

        CompletableFuture<String> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            //模拟耗时50毫秒
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "用户B";
        });

        System.out.println("获取用户信息:" + supplyAsync1.get());
        System.out.println("获取商品信息:" + supplyAsync2.get());

        //模拟主程序耗时时间
        Thread.sleep(600);
        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");
    }
}

测试结果:

获取用户信息:用户A
获取商品信息:用户B
总共用时851ms

通过CompletableFuture可以很轻松的实现CountDownLatch的功能,你以为这就结束了,远远不止,CompletableFuture比这要强多了。

比如可以实现:任务1执行完了 再执行任务2;甚至任务1执行的结果,作为任务2的入参数等等强大功能,下面就来学学CompletableFuture的API。

CompletableFuture创建方式

常用的4种创建方式:CompletableFuture源码中有四个静态方法用来执行异步任务

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier){..}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor){..}
public static CompletableFuture<Void> runAsync(Runnable runnable){..}
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor){..}
区别

supplyAsync :执行任务,支持返回值。

runAsync:执行任务,没有返回值。

结果获取的4种方式

*//方式一*
public T get()
*//方式二*
public T get(long timeout, TimeUnit unit)
*//方式三*
public T getNow(T valueIfAbsent)
*//方式四*
public T join()
补充:

get()和get(long timeout, TimeUnit unit) : 在Future中就已经提供了,后者提供超时处理,如果在指定时间内未获取结果将抛出超时异常

getNow : 立即获取结果不阻塞,结果计算已完成将返回结果或计算过程中的异常,如果未计算完成将返回设定的valueIfAbsent值

join : 方法里不会抛出异常

测试结果

第一个执行结果为 「商品B」,因为要先睡上1秒结果不能立即获取

join方法获取结果方法里不会抛异常,但是执行结果会抛异常,抛出的异常为CompletionException

get方法获取结果方法里将抛出异常,执行结果抛出的异常为ExecutionException

异步回调方法

image

1、thenRun/thenRunAsync

完成第一个任务后,执行第二个任务,第二个任务也没有返回值

代码:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        long startTime = System.currentTimeMillis();
        CompletableFuture<Void> cp1 = CompletableFuture.runAsync(() -> {
            try {
                //执行任务A
                Thread.sleep(180);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        });

        CompletableFuture<Void> cp2 =  cp1.thenRun(() -> {
            try {
                //执行任务B
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // get方法测试
        System.out.println(cp2.get());

        //模拟主程序耗时时间
        Thread.sleep(600);
        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");

    }
}
测试结果:

null
总共用时912ms

thenRun 和thenRunAsync区别

如果你执行第一个任务的时候,传入了一个自定义线程池:

  • 调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池。
  • 调用thenRunAsync执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoin线程池。

说明: 后面介绍的thenAccept和thenAcceptAsync,thenApply和thenApplyAsync等,它们之间的区别也是这个。

2、thenAccept/thenAcceptAsync

第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,但是回调方法是没有返回值的。

代码:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        long startTime = System.currentTimeMillis();
        CompletableFuture<String> cp1 = CompletableFuture.supplyAsync(() -> {
            try {
                //执行任务A
                Thread.sleep(180);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "参数";
        }).thenApply((e)->{
            if("参数".equals(e)){
                return e;
            }
            return e+"haha";
        });

        // get方法测试
        System.out.println(cp1.get());

        //模拟主程序耗时时间
        Thread.sleep(600);
        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");

    }
}
测试结果:

参数
总共用时846ms

异常回调

当CompletableFuture的任务不论是正常完成还是出现异常它都会调用「whenComplete」回调函数。

  • 「正常完成」:whenComplete返回结果和上级任务一致,异常为null;
  • 「出现异常」:whenComplete返回结果为null,异常为上级任务的异常;

即调用get()时,正常完成时就获取到结果,出现异常时就会抛出异常,需要你处理该异常。

只用whenComplete

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

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {
            if (Math.random() < 0.5) {
                throw new RuntimeException("出错了");
            }
            System.out.println("正常结束");
            return 0.11;

        }).whenComplete((aDouble, throwable) -> {
            if (aDouble == null) {
                System.out.println("whenComplete aDouble is null");
            } else {
                System.out.println("whenComplete aDouble is " + aDouble);
            }
            if (throwable == null) {
                System.out.println("whenComplete throwable is null");
            } else {
                System.out.println("whenComplete throwable is " + throwable.getMessage());
            }
        });
        System.out.println("最终返回的结果 = " + future.get());
    }
}
无异常
正常结束
whenComplete aDouble is 0.11
whenComplete throwable is null
最终返回的结果 = 0.11
异常
whenComplete aDouble is null
whenComplete throwable is java.lang.RuntimeException: 出错了
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.RuntimeException: 出错了
	at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
	at CompletableFutureTest.main(CompletableFutureTest.java:28)
Caused by: java.lang.RuntimeException: 出错了
	at CompletableFutureTest.lambda$main$0(CompletableFutureTest.java:11)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
	at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

whenComplete + exceptionally

出现异常时,exceptionally中会捕获该异常,给出默认返回值400。

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

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {
            if (Math.random() < 0.5) {
                throw new RuntimeException("出错了");
            }
            System.out.println("正常结束");
            return 0.11;

        }).whenComplete((aDouble, throwable) -> {
            if (aDouble == null) {
                System.out.println("whenComplete aDouble is null");
            } else {
                System.out.println("whenComplete aDouble is " + aDouble);
            }
            if (throwable == null) {
                System.out.println("whenComplete throwable is null");
            } else {
                System.out.println("whenComplete throwable is " + throwable.getMessage());
            }
        }).exceptionally((throwable) -> {
            System.out.println("exceptionally中异常:" + throwable.getMessage());
            // 默认值
            return 400D;
        });;
        System.out.println("最终返回的结果 = " + future.get());
    }
}
测试结果
whenComplete aDouble is null
whenComplete throwable is java.lang.RuntimeException: 出错了
exceptionally中异常:java.lang.RuntimeException: 出错了
最终返回的结果 = 400.0

多任务组合回调

image

AND组合关系

thenCombine / thenAcceptBoth / runAfterBoth:当任务一和任务二都完成再执行任务三

区别在于:

  • 「runAfterBoth」 不会把执行结果当做方法入参,且没有返回值
  • 「thenAcceptBoth」: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值
  • 「thenCombine」:会将两个任务的执行结果作为方法入参,传递到指定方法中,且有返回值
代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //开启异步任务1
        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务1,当前线程编号是:" + Thread.currentThread().getId());
            int result = 1 + 1;
            System.out.println("异步任务1结束");
            return result;
        }, executorService);

        //开启异步任务2
        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务2,当前线程编号是:" + Thread.currentThread().getId());
            int result = 1 + 1;
            System.out.println("异步任务2结束");
            return result;
        }, executorService);

        //任务组合
        CompletableFuture<Integer> task3 = task.thenCombineAsync(task2, (f1, f2) -> {
            System.out.println("执行任务3,当前线程编号是:" + Thread.currentThread().getId());
            System.out.println("任务1返回值:" + f1);
            System.out.println("任务2返回值:" + f2);
            return f1 + f2;
        }, executorService);

        Integer res = task3.get();
        System.out.println("最终结果:" + res);
    }
}
测试结果
异步任务1,当前线程编号是:20
异步任务2,当前线程编号是:21
异步任务1结束
异步任务2结束
执行任务3,当前线程编号是:22
任务1返回值:2
任务2返回值:2
最终结果:4

OR组合关系

applyToEither / acceptEither / runAfterEither :两个任务,只要有一个任务完成,就执行任务三

区别在于:

  • 「runAfterEither」:不会把执行结果当做方法入参,且没有返回值
  • 「acceptEither」: 会将已经执行完成的任务,作为方法入参,传递到指定方法中,且无返回值
  • 「applyToEither」:会将已经执行完成的任务,作为方法入参,传递到指定方法中,且有返回值
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //开启异步任务1
        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务1,当前线程编号是:" + Thread.currentThread().getId());
            int result = 1 + 1;
            System.out.println("异步任务1结束");
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return result;
        }, executorService);

        //开启异步任务2
        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务2,当前线程编号是:" + Thread.currentThread().getId());
            int result = 1 + 2;
            System.out.println("异步任务2结束");
            return result;
        }, executorService);

        //任务组合
        task.acceptEitherAsync(task2, (e) -> {
            System.out.println("执行任务3,当前线程编号是:" + Thread.currentThread().getId());
            System.out.println("上一个任务的结果为:" + e);
        }, executorService);
    }
}


测试结果:
异步任务1,当前线程编号是:20
异步任务2,当前线程编号是:21
异步任务1结束
异步任务2结束
执行任务3,当前线程编号是:22
上一个任务的结果为:3

多任务组合

  • 「allOf」:等待所有任务完成
  • 「anyOf」:只要有一个任务完成

allOf:等待所有任务完成

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

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //开启异步任务1
        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId());
            int result = 1 + 1;
            System.out.println("异步任务1结束");
            return result;
        }, executorService);

        //开启异步任务2
        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId());
            int result = 1 + 2;
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务2结束");
            return result;
        }, executorService);

        //开启异步任务3
        CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务3,当前线程是:" + Thread.currentThread().getId());
            int result = 1 + 3;
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务3结束");
            return result;
        }, executorService);

        //任务组合
        CompletableFuture<Void> allOf = CompletableFuture.allOf(task, task2, task3);

        //等待所有任务完成
        allOf.get();
        //获取任务的返回结果
        System.out.println("task结果为:" + task.get());
        System.out.println("task2结果为:" + task2.get());
        System.out.println("task3结果为:" + task3.get());
    }
}



异步任务1,当前线程是:20
异步任务2,当前线程是:21
异步任务1结束
异步任务3,当前线程是:22
异步任务2结束
异步任务3结束
task结果为:2
task2结果为:3
task3结果为:4

anyOf: 只要有一个任务完成

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

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //开启异步任务1
        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId());
            int result = 1 + 1;
            System.out.println("异步任务1结束");
            return result;
        }, executorService);

        //开启异步任务2
        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId());
            int result = 1 + 2;
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务2结束");
            return result;
        }, executorService);

        //开启异步任务3
        CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务3,当前线程是:" + Thread.currentThread().getId());
            int result = 1 + 3;
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务3结束");
            return result;
        }, executorService);

        //任务组合
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(task, task2, task3);

        //等待所有任务完成
        Object o = anyOf.get();
        //获取任务的返回结果
        System.out.println("最终结果为:" + o);

        executorService.shutdown();
    }
}




异步任务1,当前线程是:22
异步任务2,当前线程是:23
异步任务1结束
最终结果为:2
异步任务3,当前线程是:24
异步任务2结束
异步任务3结束

Completable使用注意点

CompletableFuture 使我们的异步编程更加便利的、代码更加优雅的同时,我们也要关注下它,使用的一些注意点。

1.Future需要获取返回值才能获取异常信息

2.get()的方法是阻塞的

3.不建议使用默认线程池

4.自定义线程池注意饱和策略

Future需要获取返回值才能获取异常信息
@Test
    public void testWhenCompleteExceptionally() {
        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {
            if (1 == 1) {
                throw new RuntimeException("出错了");
            }
            return 0.11;
        });

        //如果不加 get()方法这一行,看不到异常信息
        //future.get();
    }

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

/**
 * 大汉软件:CompletableFuture
 */
public class CompletableFutureTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {
            if (1 == 1) {
                throw new RuntimeException("出错了");
            }
            return 0.11;
        });

        Double aDouble = future.get();

        executorService.shutdown();
    }
}



Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.RuntimeException: 出错了
	at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
	at CompletableFutureTest.main(CompletableFutureTest.java:20)
Caused by: java.lang.RuntimeException: 出错了
	at CompletableFutureTest.lambda$main$0(CompletableFutureTest.java:15)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
	at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
get()的方法是阻塞的
//错误方式
 CompletableFuture.get();
//正确方式
CompletableFuture.get(5, TimeUnit.SECONDS);

不建议使用默认线程池

CompletableFuture代码中又使用了默认的「ForkJoin线程池」,处理的线程个数是电脑「CPU核数-1」。在大量请求过来的时候,处理逻辑复杂的话,响应会很慢。一般建议使用自定义线程池,优化线程池配置参数。

自定义线程池时,注意饱和策略

CompletableFuture的get()方法是阻塞的,建议使用future.get(5, TimeUnit.SECONDS)。并推荐使用自定义线程池。

但是如果线程池拒绝策略是DiscardPolicy或者DiscardOldestPolicy,当线程池饱和时,会直接丢弃任务,不会抛弃异常。

因此建议,CompletableFuture线程池策略最好使用AbortPolicy,然后耗时的异步线程,做好线程池隔离

标签:异步,java,System,线程,println,CompletableFuture,多线程
From: https://www.cnblogs.com/csh520mjy/p/17093734.html

相关文章

  • Java多线程并发06—CAS、AQS
    CAS(CompareAndSwap/Set)概念CAS函数,是比较并交换函数,它是原子操作函数。原理CAS是基于乐观锁的原理进行操作的。它总是认为自己可以成功完成操作。当多个线程同时使用CAS......
  • 多线程
    多线程多任务看起来是多个任务都在做,其实本质上是同一时间只做了一件事情多线程普通方法调用多线程方法调用​ 程序.进程.线程......
  • 多线程之countDownlLatch项目使用
    packagecom.company;importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.*;publicclassMain{publicstaticvoidmain(Strin......
  • 探秘多线程-闭锁、栅栏与异步编排
    无论是项目开发还是开源代码阅读,多线程都是不可或缺的一个重要知识点,基于这个考量,于是总结出本篇文章,讨论闭锁(CountDownLatch)、栅栏(CyclicBarrier)与异步编排(CompletableF......
  • Java多线程01——多线程的创建
    1进程和线程进程:进程是并发执行程序在执行过程中,资源分配和管理的基本单位。进程可以理解为一个应用程序的执行过程,应用程序一旦执行,就是一个进程。线程:线程是进程的一个执......
  • Java 多线程学习
    Java多线程学习Thread类学习首先使类继承Thread然后创建run方法其中在线程中run主要是线程执行体在线程中new这个类然后使用start进行线程打开注:线程中是同......
  • Java多线程并发04—线程池的合理使用
    为什么使用线程池?线程池做的工作主要是控制运行的线程的数量。线程池的种类Java中常用的线程池主要有四种:newCachedThreadPool、newFixedThreadPool、newScheduledThreadPo......
  • Java多线程并发05-锁说明
    根据锁的各种特性,可将锁分为以下几类:乐观锁/悲观锁独享锁(互斥锁)/共享锁(读写锁)可重入锁公平锁/非公平锁分段锁偏向锁/轻量级锁/重量级锁自旋锁乐观锁/悲观锁乐观锁与悲观锁并......
  • Qt 中多线程的使用
    前言在进行桌面应用程序开发的时候,假设应用程序在某些情况下需要处理比较复杂的逻辑,如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。这种情况下就需要使......
  • Java多线程并发03—线程上下文,线程调度
    多任务系统往往需要同时执行多道作业。作业数往往大于机器的CPU数,然而一颗CPU同时只能执行一项任务,如何让用户感觉这些任务正在同时进行呢?操作系统的设计者巧妙地利......