java同步方法和异步方法,java异步调用方法,Java 异步实现的几种方式小结

java同步方法和异步方法,java异步调用方法,Java 异步实现的几种方式小结

本文主要介绍了Java异步实现的几种方式的总结,具有很好的参考价值,希望对大家有所帮助。如有错误或不足之处,请不吝赐教。

Java 异步实现的几种方式

1. jdk1.8之前的Future

jdk的平行契约中的未来代表了一个未来的结果。当我们向线程池提交一个任务时,我们会返回这个对象,我们可以通过未来得到执行结果。但是jdk1.8之前的未来有点鸡肋,无法实现真正的异步。它需要阻塞来获得结果,或者持续轮询。

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

/**

* JDK 1.8之前的未来

* @作者管理员

*/

公共类JavaFuture {

公共静态void main(String[] args)引发Throwable,ExecutionException {

ExecutorService executor=executors . newfixedthreadpool(1);

future string f=executor . submit(new callable string(){

@覆盖

公共字符串调用()引发异常{

System.out.println('任务已启动!');

long time method();

System.out.println('任务完成!');

回‘你好’;

}

});

//这里get()方法阻塞了主线程

system . out . println(f . get());

System.out.println(“主线程被阻塞”);

}

}

如果想得到耗时操作的结果,可以通过get()方法得到,但是这个方法会阻塞当前线程。当我们完成一些剩余的工作时,我们可以调用get()方法来尝试获得结果。

还可以调用非阻塞方法isDone来确定操作是否完成,这与下面的过程有些类似:

2. jdk1.8开始的Future

直到jdk1.8才真正支持异步操作,jdk1.8中提供了lambda表达式,让java离函数式语言更近了一步。借助jdk的native CompletableFuture可以实现异步操作,结合lambada表达式可以大大简化代码量。代码示例如下:

包netty _ promise

导入Java . util . concurrent . completablefuture;

import Java . util . concurrent . execution exception;

导入Java . util . concurrent . executorservice;

导入Java . util . concurrent . executors;

导入Java . util . function . supplier;

/**

*基于jdk1.8的任务异步处理

* @作者管理员

*/

公共类JavaPromise {

公共静态void main(String[] args)引发Throwable,ExecutionException {

//两个线程的线程池

ExecutorService executor=executors . newfixedthreadpool(2);

//jdk1.8之前的实现

CompletableFutureString future=completablefuture . supplyasync(new SupplierString(){

@覆盖

公共字符串get() {

System.out.println('任务已启动!');

尝试{

//模拟耗时的操作

long time method();

} catch (InterruptedException e) {

e . printstacktrace();

}

返回“任务完成!”;

}

},执行人);

//采用lambada的实现方式

future . then accept(e-system . out . println(e ' ok '));

System.out.println('主线程正在运行');

}

}

实现类似于下图:

3. Spring的异步方法

先把longTimeMethod封装到Spring的异步方法中,这个异步方法的返回值是Future的一个实例。这个方法必须写在Spring管理的类中。注意@Async。

@服务

公共类异步服务{

@Async

public Future springAsynchronousMethod(){

整数result=long time method();

返回新的AsyncResult(结果);

}

}

其他类调用此方法。这里很重要的一点是,其他类如果在同一个类中调用,是不会生效的。

@自动连线

私有异步服务异步服务;

public void useAsynchronousMethod(){

future future=asynchronous service . spring asynchronous method();

future.get(1000,时间单位。毫秒);

}

实际上,Spring只在原生的Future中封装了一次,我们最终得到的是Future实例。

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

换句话说,需要阻塞异步调用,直到获得调用结果。

使用等待和通知方法。

使用条件锁

将来的

使用CountDownLatch

使用循环屏障

五种方法,具体例子见这篇文章

java异步任务处理

1、场景

最近在做项目的时候遇到了一个小问题:从前台提交到服务器A,服务器B被A调用处理超时。原因是前端曾经请求向db中插入10000个数据,插入后会清空缓存并发送消息。

服务器端有三个操作:A、插入DB b、清理缓存c、发送消息。一万条数据,多说,少说。而且,不仅仅是插入。出现超时现象不奇怪~ ~

2、分析

如何避免超时?一个请求可以处理太多的数据,这些数据可以分成多个请求。每个请求可以处理100条数据,可以有效解决超时问题。为了不影响用户体验,请求改为ajax异步请求。

另外,仔细分析场景。操作A是这个处理的核心,而操作B和C可以异步处理。换句话说,操作A可以在处理后立即返回结果,不需要等B和C处理完再返回。b和C操作可以在异步任务中处理。

3、实战

(1)执行者服务:任务提交

(2)、演示

异步任务类

公共类执行器演示{

private ExecutorService executor=executors . newfixedthreadpool(1);

public void asynTask()引发InterruptedException {

executor.submit(new Runnable() {

@覆盖

公共无效运行(){

尝试{

thread . sleep(10000);//方便观察结果

} catch (InterruptedException e) {

e . printstacktrace();

}

int sum=0;

for(int I=0;i 1000i ) {

sum=I;

}

system . out . println(sum);

}

});

}

}

客户端模拟

公共类客户端{

公共静态void main(String[] args)引发InterruptedException {

布尔型r=task 2();

如果(r) {

task 3();

}

system . out . println('-main end-');

}

静态布尔task2()引发InterruptedException {

executor demo e=new executor demo();

e . asyntask();

system . out . println('-task 2 end-');

返回true

}

静态void task3()引发InterruptedException {

int j=0;

while(true) {

如果(j 10000) {

打破;

}

}

system . out . println('-task 3 end-');

}

}

原来是酱紫。

-任务2结束-

-任务3结束-

-主端-

499500

我们来分析一下结果。task2是一个异步任务。当它执行到task2时,主线程不会在task2处被阻塞,所以可以执行task3,而不用等待task2完成处理。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: