В Интернете есть много статей, объясняющих этот шаблон проектирования, и многие материалы и методы более полны и глубоки, чем я! Но так как учусь, я все же хочу сделать резюме! Я надеюсь, что вы можете получить вдохновение от чтения этой статьи!
Когда дело доходит до параллельного программирования, мы все думаем: «Вау, параллельное программирование — это действительно сложно!» Но так ли это на самом деле? Я так не думаю, как только появится технология, пока у вас есть решимость победить ее, вы победите. Вот что мы часто говорим: "Стабильность, жалкий рост, не колеблясь, мы можем победить!" В процессе обучения обязательно будут некоторые трудности. Это очень хороший способ найти больше людей, с которыми можно пообщаться и сделать прогресс друг с другом Xiaobian Я надеюсь, что вы можете общаться с редактором после прочтения статьи, которую я резюмировал, это не большая честь.
1. Что такое асинхронность?
Прежде чем объяснять шаблон проектирования, позвольте мне поговорить об асинхронности. Асинхронность и синхронизация противоположны. Эти два понятия на самом деле несложно понять. Ключ в том, как синхронизация и асинхронность отражаются в программе, что нас больше всего интересует и хочу, чтобы большинство знали.
同步
: То есть, когда задача A зависит от выполнения задачи B, задача A должна дождаться завершения выполнения задачи B, прежде чем задача A продолжит выполнение, и задача A блокируется во время этого процесса. Миссии либо все завершатся успешно, либо все провалятся! Только подумайте о нашем телефонном звонке!异步
: Задача A вызывает задачу B. Задаче A не нужно ждать завершения задачи B. Задача B просто возвращает фиктивный результат задаче A, так что задача A может продолжать выполнять другие действия, а затем уведомляет задачу A (обратный вызов). после завершения задачи B.) или задача A активно запрашивает задачу B для получения результата. Только подумайте о смс!
два,Future
Шаблоны асинхронного проектирования
Сначала нашел картинку в интернете и сравнил их по отдельности.异步
а также同步
Разница во времени:
Так как же нам этого достичь? Сначала опубликуйте диаграмму UML, а затем скажите:
Прежде чем объяснять пример, я считаю необходимым упомянуть некоторые предпосылки:
- 1,
notify/wait
Каждый объект java имеет эти два метода, и вызов этих двух методов должен сначала получить монитор, обычная практика заключается в том, чтобыsynchronized
вызов в синхронизированном блоке - 2,
生产者/消费者
Модель, на самом деле, это необязательно, главное не писать ее вif(块中)
перечислитьnotify/wait
метод вместоwhile
Все мои логические комментарии вкраплены в код ниже.Если есть вопросы, с которыми вы хотите пообщаться, комментарии приветствуются, комментарии приветствуются, комментарии приветствуются!
Main.java
package com.wokao66.future;
/**
* 持有一个客户端Client对象,发送请求
* @author: huangjiawei
* @since: 2018年4月2日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class Main {
public static void main(String[] args) throws Exception {
/**
* 持有一个客户端Client对象
*/
Client client = new Client();
/**
* 返回一个虚拟的数据(这是异步返回的,虚拟的,不是真实的,但必须持有真实数据对象realData,方便后面获取请求结果)
*/
Data virtualData = client.request("我要下单!!!!");
/**
* 睡眠5秒
*/
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
/**
* 我现在想获得真实数据了
*/
String realData = virtualData.getResultData();
System.err.println("真实数据为:" + realData);
}
}
Data.java
package com.wokao66.future;
/**
* 对返回数据的简单抽象(虚拟数据和真实数据都必须实现该接口)
* @author: huangjiawei
* @since: 2018年4月2日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public interface Data {
/**
* 获取数据的操作,至于是虚拟的,还是真实的,我不用管,让实现类去决定
* @throws Exception
*/
public abstract String getResultData() throws Exception;
}
VirtualData.java
package com.wokao66.future;
/**
* 虚拟的数据(异步返回给客户端)
* @author: huangjiawei
* @since: 2018年4月2日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class VirtualData implements Data {
/**
* 想象一下,如果你这里返回的VirtualData不包含对RealData的引用,那么当客户端需要获取真实数据时,你的数据从何而来???
*/
private RealData realData = null;
/**
* 默认是还没有准备好数据嘛!要有个状态来跟踪
*/
private boolean isReady = false;
/**
* 注入RealData,这个RealData
* @param realData
*/
public synchronized void setRealData(RealData realData) {
System.err.println("获得锁");
/**
* 如果还没有准备好,我就需要
*/
if (isReady) {
return;
}
this.realData = realData;
isReady = true;//我已经准备好了
notify();//通知所有阻塞的线程
}
/**
* 重写获取数据的方式
* @throws Exception
*/
@Override
public synchronized String getResultData() throws Exception {
/**
* 如果客户端调用的时候我还没有注入真实数据,那么就一直阻塞
*/
while (!isReady) {
//调用wait必须先获得对象的锁,所以
wait();
}
return realData.getResultData();
}
}
RealData.java
package com.wokao66.future;
/**
* 这个类表示你具体的业务操作,比如重数据库查询数据
* @author: huangjiawei
* @since: 2018年4月2日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class RealData implements Data {
/**
* 请求名
*/
private String readData;
public RealData(String readData) {
/**
* 我这里先休眠10秒,表示一个耗时的操作
*/
try {
Thread.sleep(10000);
} catch (InterruptedException e) {}
this.readData = "调用名为 : " + readData + " , " + "真实的数据为 : realData";
}
@Override
public String getResultData() {
return readData;
}
}
Client.java
package com.wokao66.future;
/**
* 表示我们的客户端程序嘛!负责发起调用请求
* @author: huangjiawei
* @since: 2018年4月2日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class Client {
/**
* 表示客户端的请求
* @param name 具体的请求名称
* @return
*/
public Data request(String name) {
/**
* 声明一个虚拟的数据
*/
VirtualData virtualData = new VirtualData();
/**
* 当你调用请求时,我后台默默开启一个线程去处理真实操作
*/
new Thread(new Runnable() {
@Override
public void run() {
System.err.println("我偷偷摸摸地请求后台获取数据的操作,该操作可能会执行很长的时间");
System.err.println("我不管了,先返回结果给调用方");
RealData realData = new RealData(name);
//下面两句的执行顺序是不一样的
//启动线程
virtualData.setRealData(realData);
}
}).start();
//我先返回一个虚拟的数据给你,真的数据等我获取完成之后你再过来取
return virtualData;
}
}
运行结果
下单成功...............
我偷偷摸摸地请求后台获取数据的操作,该操作可能会执行很长的时间
我不管了,先返回结果给调用方
获得锁
真实数据为:调用名为 : 我要下单!!!! , 真实的数据为 : realData
Я не знаю, думал ли ты об этом,Main.java
серединаString realData = virtualData.getResultData();
Это локальный объект и может выполняться только локально Что, если это сетевая передача на основе tcp? Вы можете использовать push, websocket и т. д.,dubbo
Предсказание тоже возможно! Правильно, вдруг вспомнилось,Java EE 7
Асинхронность уже поддерживаетсяServlet
Теперь вы можете проверить соответствующие документы для деталей!
3. Асинхронное параллельное программирование на Java
Результаты асинхронного выполнения представляют собой не что иное, как две формы:
- 1. Есть обратный вызов после выполнения
- 2. Нет обратного вызова после выполнения
有回调
Обращается к клиенту для установления соответствующего监听器Listener
, сервер выполняется асинхронноFuture
Затем активно вызывайте функцию обратного вызова клиента.
无回调
То есть, как мы упоминали в предыдущем примере, нам нужно активно запрашивать сервер, чтобы оценить, был ли он успешным или нет.
package com.wokao66.javafuture;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main(String[] args) {
/**
* 新建一个线程池
*/
ExecutorService executor = Executors.newFixedThreadPool(1);
/**
* 创建一个任务
*/
Task task = new Task();
/**
* 将任务提交给线程池
*/
Future<Integer> result = executor.submit(task);
//这里会保证所有子线程执行完毕再关闭
executor.shutdown();
try {
/**
* 模拟执行其它操作
*/
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("我在执行其他操作........");
try {
System.out.println("任务的执行结果是:" + result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class Task implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("子线程在进行计算");
/**
* 模拟执行耗时操作
*/
Thread.sleep(10000);
return 100;
}
}
Результаты
子线程在进行计算
我在执行其他操作........
任务的执行结果是:100
Также можно использовать javaFutureTask
создавать задачи,FutureTask
ОдновременноRunnable
а такжеCallable
Интерфейс, очень удобный!
Спасибо за прочтение!