Future&CompletableFuture&Disruptor实战

目录

1. 为什么需要callable接口

1.1 future

1.1.1 同步执行任务实战

1.1.2 futureTask执行任务实战 

1.2 CompletableFuture

1.2.1 CompletableFuture实战

2.Disruptor

 2.1 disruptor使用


1. 为什么需要callable接口

传统的创建线程方式有两种:继承Thread和实现Runnable接口,两个都没有返回值,而且不能抛出异常。为了解决这个问题,java可以通过实现callable接口,重写call方式返回任务结果。

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

public class ThreadTest {

    public static void main(String[] args) {
        //实现线程的方式使用jdk8-lamda表达式写法
        new Thread(()->{
            System.out.println("通过Thread类实现");
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("通过runnable实现");
            }
        }).start();
    }
}

1.1 future

future能够跟callable结合使用,可以获取callable接口的结果,或者取消任务

future的实现类futureTask能够帮忙我们实现。

futureTask的重要方法:

        public boolean isDone() 任务是否已经完成。总会返回true。

        public V get() throws InterruptedException, ExecutionException 获取任务结果,会阻塞线程直到返回结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出 CancellationException

        public boolean cancel(boolean mayInterruptIfRunning) 取消任务

        public boolean isCancelled() 是否取消任务

        public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 超时获取任务执行结果

Future和callable不产生新的线程。

当有多个任务采用以下同步方式获取任务,任务执行时间是叠加的,当我们使用futureTask时,只需要执行任务的时间50ms即可。在真实的业务中,可能存在不同业务执行时间超过50ms的情况,使用并行执行能大大减少业务等待时间。

1.1.1 同步执行任务实战

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

public class ThreadTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //实现线程的方式futureTask
        FutureTask task = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                return "返回callable执行结果";
            }
        });

        new Thread(task).start();
        System.out.println("获取结果:"+task.get());

    }
}

1.1.2 futureTask执行任务实战 

当我们使用furuteTask批量获取任务结果时,可能会存在阻塞的情况,需要使用 get(timeout,TimeUnit)方法来获取任务执行结果。为了解决批量获取任务结果的情况,我们也可以采用completionService,可以一边获取结果,一边执行任务。

import java.util.concurrent.*;

public class ThreadTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //1. 定义5个FutureTask任务
        FutureTask futureTask1 = new FutureTask(new Task1());
        FutureTask futureTask2 = new FutureTask(new Task2());
        FutureTask futureTask3 = new FutureTask(new Task3());
        FutureTask futureTask4 = new FutureTask(new Task4());
        FutureTask futureTask5 = new FutureTask(new Task5());
        //2. 定义一个定长线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //3. 提交任务到线程池
        executorService.submit(futureTask1);
        executorService.submit(futureTask2);
        executorService.submit(futureTask3);
        executorService.submit(futureTask4);
        executorService.submit(futureTask5);
        //4. 获取任务结果,关闭线程池
        System.out.println("获取任务结果:"+futureTask1.get());
        System.out.println("获取任务结果:"+futureTask2.get());
        System.out.println("获取任务结果:"+futureTask3.get());
        System.out.println("获取任务结果:"+futureTask4.get());
        System.out.println("获取任务结果:"+futureTask5.get());
        executorService.shutdown();
    }
}

class Task1 implements Callable{

    @Override
    public Object call() throws Exception {
        Thread.sleep(50);
        return "任务1返回结果";
    }
}

class Task2 implements Callable{

    @Override
    public Object call() throws Exception {
        Thread.sleep(50);
        return "任务2返回结果";
    }
}

class Task3 implements Callable{

    @Override
    public Object call() throws Exception {
        Thread.sleep(50);
        return "任务3返回结果";
    }
}


class Task4 implements Callable{

    @Override
    public Object call() throws Exception {
        Thread.sleep(50);
        return "任务4返回结果";
    }
}


class Task5 implements Callable{

    @Override
    public Object call() throws Exception {
        Thread.sleep(50);
        return "任务5返回结果";
    }
}

1.2 CompletableFuture

CompletableFuture是对future的补充,能够用来描述串行,并行,聚合的关系。

应用场景:

依赖关系:

thenApply(Function<? super T,? extends U> fn)
thenCompose()用来连接两个有依赖关系的任务,结果由第二个任务返回
描述and聚合关系: 
1. thenCombine:任务合并,有返回值 
2. thenAccepetBoth:两个任务执行完成后,将结果交给thenAccepetBoth消耗,无返回值。 
3. runAfterBoth:两个任务都执行完成后,执行下一步操作(Runnable)。
描述or聚合关系:1.applyToEither 2.acceptEither 3.runAfterEither
并行执行:CompletableFuture类自己也提供了anyOf()和allOf()用于支持多个CompletableFuture 
创建异步操作
public static CompletableFuture < Void > runAsync ( Runnable runnable )
public static CompletableFuture < Void > runAsync ( Runnable runnable , Executor e
xecutor )
public static < U > CompletableFuture < U > supplyAsync ( Supplier < U > supplier )
public static < U > CompletableFuture < U > supplyAsync ( Supplier < U > supplier , Exe
cutor executor )
get和join方法区别:join方法可以不用抛出异常,get方法需要抛出异常处理

1.2.1 CompletableFuture实战

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

public class CompletableFutureTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Runnable runnable = ()-> System.out.println("执行无返回结果的异步任务");
        CompletableFuture.runAsync(runnable);

        //执行有返回结果的异步任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行无返回结果的异步任务");
            return "Hello World";
        });

        //获取任务
//        System.out.println(future.get());
        System.out.println(future.join());
    }
}

2.Disruptor

Disruptor是一个功性能的队列,用于解决内存队列的延迟问题。其他的队列会存在

1.伪共享 2.加锁reentrantlock会影响性能

设计方案:1.环形数组 2.元素位置定位 3.无锁设计 4.利用缓冲行填充解决了伪共享问题 5.基于事件驱动的生产者消费者模型

没啥用,随便看看吧!

 2.1 disruptor使用

1.引入依赖

<!‐‐ disruptor ‐‐>
< dependency >
< groupId > com . lmax </ groupId >
< artifactId > disruptor </ artifactId >
< version > 3.3.4 </ version >
</ dependency >
2. 构建消息载体(事件)
3. 构建生产者
4. 构建消费者
5. 生产者消费者测试

猜你喜欢

转载自blog.csdn.net/qq_21575929/article/details/124916089
今日推荐