欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Java 如何实现异步(通过子线程)

最编程 2024-07-16 14:25:27
...

1. jdk1.8之前的Future

jdk并发包里的Future代表了未来的某个结果,当我们向线程池中提交任务的时候会返回该对象,可以通过future获得执行的结果,但是jdk1.8之前的Future有点鸡肋,并不能实现真正的异步,需要阻塞的获取结果,或者不断的轮询。

通常我们希望当线程执行完一些耗时的任务后,能够自动的通知我们结果,很遗憾这在原生jdk1.8之前是不支持的,但是我们可以通过第三方的库实现真正的异步回调。

/**
* jdk1.8之前的Future
* @author Administrator
*/
public class JavaFuture {
public static void main(String[] args) throws Throwable, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> f = executor.submit(new Callable<String>() {

@Override
public String call() throws Exception {
System.out.println("task started!");
longTimeMethod();
System.out.println("task finished!");
return "hello";
}
});

//此处get()方法阻塞main线程
System.out.println(f.get());//这里需要等待执行结果
System.out.println("main thread is blocked");
}
}

如果想获得耗时操作的结果,可以通过get()方法获取,但是该方法会阻塞当前线程,我们可以在做完剩下的某些工作的时候调用get()方法试图去获取结果。

也可以调用非阻塞的方法isDone来确定操作是否完成,isDone这种方式有点儿类似下面的过程:(同步非阻塞)

2. jdk1.8开始的Future

直到jdk1.8才算真正支持了异步操作,jdk1.8中提供了lambda表达式,使得java向函数式语言又靠近了一步。借助jdk原生的CompletableFuture可以实现异步的操作,同时结合lambada表达式大大简化了代码量。代码例子如下:

简单异步实现

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

public class JavaPromise {
   public static void main(String[] args) throws Throwable, ExecutionException {
       // 两个线程的线程池
       ExecutorService executor = Executors.newFixedThreadPool(2);
       //jdk1.8之前的实现方式
       CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
           @Override
           public String get() {
               System.out.println("task started!");
               try {
                   //模拟耗时操作
                   Thread.sleep(5000);
              } catch (InterruptedException e) {
                   e.printStackTrace();
              }
               return "task finished!";
          }
      }, executor);//这里会直接运行这个代码

       //采用lambada的实现方式
       future.thenAccept(e -> System.out.println(e + " ok"));

       System.out.println("main thread is running");
  }

}

执行结果:
task started!
main thread is running
task finished! ok




3. Java如何将异步调用转为同步

换句话说,就是需要在异步调用过程中,持续阻塞至获得调用结果。

    • 使用wait和notify方法

    • 使用条件锁

    • Future

    • 使用CountDownLatch

    • 使用CyclicBarrier

推荐阅读