Поговорите о параллельном шаблоне проектирования --- Будущее (асинхронное)

Java задняя часть Шаблоны проектирования UML
Поговорите о параллельном шаблоне проектирования --- Будущее (асинхронное)

В Интернете есть много статей, объясняющих этот шаблон проектирования, и многие материалы и методы более полны и глубоки, чем я! Но так как учусь, я все же хочу сделать резюме! Я надеюсь, что вы можете получить вдохновение от чтения этой статьи!

Когда дело доходит до параллельного программирования, мы все думаем: «Вау, параллельное программирование — это действительно сложно!» Но так ли это на самом деле? Я так не думаю, как только появится технология, пока у вас есть решимость победить ее, вы победите. Вот что мы часто говорим: "Стабильность, жалкий рост, не колеблясь, мы можем победить!" В процессе обучения обязательно будут некоторые трудности. Это очень хороший способ найти больше людей, с которыми можно пообщаться и сделать прогресс друг с другом 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Интерфейс, очень удобный!

Спасибо за прочтение!