作为后端工程师,我们面临着异步处理数据的情况。今天,让我们看看它是如何在Java中完成的以及各种实现方式。
从Thread,Runnable,Callable <T>,Future <T>(及其扩展的ScheduledFuture <T>),CompletableFuture <T>开始,当然还有ExecutorService和ForkJoinPool。我们将一一看到。
Thread,Runnable,Callable <T>,Future <T>
ScheduledFuture <T>),CompletableFuture <T>
ExecutorService
ForkJoinPool
线 Java并发的非常基本但功能强大的组件是Thread。Java线程实际上与操作系统的线程相关联。创建a的最基本方法Thread是扩展它并覆盖run方法:
public class TestThread extends Thread{ @Override public void run() { // Logic super.run(); } } TestThread t = new TestThread(); // starts thread t.start();// starting the thread, causes the run method be called
启动线程将导致该run()方法被调用。 您可能会问;是的,Thread有大量其他可以重写的方法:
run()
可运行 Runnable是只有一种方法的接口:run()。是的,Runnable是一个功能接口,可以使用lambda函数创建其实例。但这是一种简单的方法。对于复杂的事情,我们可能希望实现它。看到这里的区别。一切都与要求有关:
// With lambda Runnable runnable = ()->System.out.println("I'm a runnable from lambda."); // With implemention, we can hold the data and related stuff that we want to process. // Otherwise we got to manage them in the launching thread public class RunnableImplemented implements Runnable{ List<Object> mayBeAListOfData; Object mayBeAService; Object mayBeADao; public RunnableImplemented(List<Object> mayBeAListOfData, Object mayBeAService, Object mayBeADao) { super(); this.mayBeAListOfData = mayBeAListOfData; this.mayBeAService = mayBeAService; this.mayBeADao = mayBeADao; } @Override public void run() { // code logic } }
尽管Runnable有一个run()方法,但它不是一个Thread,而只是一个Java类,直到它被(传递给)Thread控制为止。线程的启动导致可运行对象的run()方法被调用。
public class TestThread { private static Runnable runnable = ()->System.out.println("I'm a runnable from lambda."); public static void main(String[] args) { Thread t = new Thread(runnable);// takes runnable here t.start(); } }
很酷,我们学习了如何使用Thread和Runnable创建线程。但是您是否注意到Thread(或Runnable),
Callable
可调用是通用接口。为什么?返回值的类型为通用类型。Callable也是一个功能性接口,并且call()是唯一的方法,它是引发Exception并返回泛型类型值的无参数方法。
实现Callable与Runnable非常相似:
private static Callable<Integer> callable = ()-> { String data = "I'm in callable."; System.out.println(); return data.length(); }; public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Integer> callFuture = executor.submit(callable); Integer integer = callFuture.get(); }
参见此处,该call方法处理数据并返回一个可以在执行后收集的值。但是调用它有很大的不同吗?我们ExecutorService用来调用和Future保存结果。让我们说说为什么。
如您所见,创建和运行线程(Runnable或Callable)也不受控制。我们可能希望控制一次运行的线程数,因为每个线程都与OS的线程相关联。我们运行的线程数应少于可用的CPU内核数。总之,Java通过ExecutorService接口解决了它。
我认为今天确实很多。也许在第二部分中,我们将讨论执行器和不同类型的ExecutorService,以及Future <V>接口。
Future <V>
原文链接:http://codingdict.com