欢迎访问宙启技术站
智能推送

如何在Java中使用线程异步函数

发布时间:2023-05-28 17:17:09

在Java中,线程是一种非常强大的工具,可以帮助我们实现并发和异步编程。异步函数通常用于需要等待一些操作结果的场合,比如网络请求或者IO操作,为了提高程序效率而不阻塞主线程的执行。在本文中,我们将学习如何在Java中使用线程异步函数。

1.创建异步函数

在Java中,我们可以使用Java Future和Java CompletableFuture类来创建异步函数。首先,我们来看一下Java Future类的用法。

Java Future是一个接口,它表示了一个异步运行的任务的未来结果。我们可以通过调用Future.get()方法来等待结果的返回,该方法会阻塞当前线程直到返回结果。我们还可以调用Future.isDone()方法来判断结果是否已经返回。

下面是一个简单的Java Future的示例代码:

import java.util.concurrent.*;

public class FutureExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<Integer> future = executorService.submit(() -> {
            Thread.sleep(1000);
            return 42;
        });
        while (!future.isDone()) {
            System.out.println("任务运行中......");
            Thread.sleep(500);
        }
        System.out.println("任务执行结束,结果是:" + future.get());
        executorService.shutdown();
    }
}

在这个示例中,我们通过创建一个ExecutorService对象来实现异步执行。我们调用了ExecutorService.submit()方法来提交一个Task对象,该对象表示了我们要执行的任务。Task对象是一个Lambda表达式,它会在子线程中执行一个模拟任务,并返回一个结果。在while循环中,我们不断地检查任务是否完成,如果还没有完成,就打印"任务运行中......"的消息并等待500毫秒。最后,我们调用Future.get()方法来等待结果的返回,并打印结果。

2.创建Java CompletableFuture

Java CompletableFuture是Java 8中新增的一个类,它是Future的一个扩展,支持更多的操作。与Java Future不同的是,Java CompletableFuture可以被用于处理异步事件。Java CompletableFuture类有两个静态工厂方法:supplyAsync()和runAsync()。

supplyAsync()方法接受一个Supplier对象作为参数,Supplier会被异步执行,而且可以是有返回值的。runAsync()方法接受一个Runnable对象作为参数,Runnable会被异步执行,没有返回值。我们可以从Java CompletableFuture的实例中获取结果,也可以对结果执行操作,比如转换或者合并。

下面是一个Java CompletableFuture的示例代码:

import java.util.concurrent.*;

public class CompletableFutureExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, CompletableFuture";
        });
        System.out.println("主线程运行......");
        String result = future.get();
        System.out.println("任务执行结束,结果是:" + result);
    }
}

在这个示例中,我们通过创建一个CompletableFuture对象来实现异步执行。我们调用了CompletableFuture.supplyAsync()方法来提交一个Supplier对象,该对象表示了我们要执行的任务。在计算完成后,我们将在Future中得到结果。在主线程等待的时候,我们可以做一些其他的工作。在打印结果之后,我们看到该任务在子线程中异步完成了。

3.链式处理异步事件

Java CompletableFuture还支持链式处理异步事件。Java CompletableFuture在执行完成之后,可以根据返回的结果来执行一些操作。我们可以使用thenApply()、thenAccept()和thenRun()方法来进行链式处理。

thenApply()方法接收一个Function对象作为参数,该对象会在CompletableFuture计算完成之后被调用。该函数会接收当前CompletableFuture的结果作为输入,并返回一个新的值。thenAccept()方法接收一个Consumer对象作为参数,该对象会在CompletableFuture计算完成之后被调用,它接收当前CompletableFuture的结果作为输入,但是不返回任何结果。thenRun()方法接收一个Runnable对象作为参数,该对象会在CompletableFuture计算完成之后被调用,没有输入和输出。

下面是一个Java CompletableFuture的链式处理示例代码:

import java.util.concurrent.*;

public class CompletableFutureExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, CompletableFuture";
        });
        System.out.println("主线程运行......");
        future
                .thenApply(result -> result + " 1")
                .thenAccept(result -> System.out.println("任务执行结束,结果是:" + result));
        System.out.println("继续执行主线程......");
        Thread.sleep(2000);
    }
}

在这个示例中,我们使用thenApply()方法来增加CompletableFuture的计算结果,并使用thenAccept()方法来打印结果,并在主线程中做其他的工作。在打印结果之前,我们没有阻塞主线程,可以做其他的事情。

4.错误处理

Java CompletableFuture类在异步执行任务的过程中,有可能会出现异常。Java CompletableFuture提供了一些方法来处理异常。

下面是一个Java CompletableFuture的错误处理示例代码:

import java.util.concurrent.*;

public class CompletableFutureExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (Math.random() < 0.5) {
                throw new RuntimeException("任务执行失败");
            }
            return "Hello, CompletableFuture";
        });
        System.out.println("主线程运行......");
        future
                .thenApply(result -> result + " 1")
                .thenAccept(result -> System.out.println("任务执行结束,结果是:" + result))
                .exceptionally(throwable -> {
                    System.out.println("任务执行失败,原因是:" + throwable.getMessage());
                    return null;
                });
        System.out.println("继续执行主线程......");
        Thread.sleep(2000);
    }
}

在这个示例中,我们通过添加一个异常处理的方法来处理CompletableFuture中产生的异常。在thenAccept()方法之后,我们添加了一个exceptionally()方法,该方法接收一个Function对象作为参数。如果CompletableFuture在执行期间抛出了异常,该方法会被调用来处理异常,否则只会打印结果。在这个示例中,我们模拟了一个随机异常,在打印"Hello, CompletableFuture"之前,如果随机数小于0.5,则抛出一个RuntimeException。

总结

Java中,使用线程异步函数可以帮助我们实现非阻塞的功能。在本文中,我们学习了Java Future和Java CompletableFuture类的用法。Java Future类可以被用于处理异步任务,Java CompletableFuture类支持更多的操作,比如链式处理等。在实际应用中,可以根据具体需求选择合适的类来实现异步编程。同时,我们还介绍了错误处理的方法,帮助我们处理任务中可能产生的异常。在实际应用中,我们应该优先使用Java CompletableFuture类来实现异步函数。