Java异步编程:第一部分


作为后端工程师,我们面临着异步处理数据的情况。今天,让我们看看它是如何在Java中完成的以及各种实现方式。

Thread,Runnable,Callable <T>,Future <T>(及其扩展的ScheduledFuture <T>),CompletableFuture <T>开始,当然还有ExecutorServiceForkJoinPool。我们将一一看到。

线 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有大量其他可以重写的方法:

  • 在大多数情况下,我们不想覆盖线程的其他方法。
  • 一旦扩展了Thread类,由于Java不支持多重继承,扩展类便失去了进一步扩展的能力。
  • 每个线程在扩展时都有其自己的对象,并且当创建大量扩展对象时,这不利于内存健康Thread。 Java通过Runnable接口解决了这些问题。实际上,线程有一个采用Runnable的重载方法。

可运行 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),

  • 该Runnable方法什么都不返回?
  • 也没有异常处理。您必须用try and catch块包围引发Exception的代码 是的,Java在1.5版中解决了它,它是Callable

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>接口。


原文链接:http://codingdict.com