1. node.js中基本上都是采用异步的事件驱动模型来实现的,如何采用Java代码实现一个异步的事件驱动模型呢?下面的例子的场景是模拟借阅者向图书管理员借书。
/**
* 图书借阅者
* <p>
* 图书借阅者的行为便是借书,其中需要与图书管理员交互
* 所以需要持有管理员的引用
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Person {
String username;
Integer age;
LibraryAdmin admin;
public void doSomething() {
IntStream.rangeClosed(1, 10).forEach(i -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开始去做其他事情" + i);
});
}
/**
* 联系图书管理员
*/
public void connect(LibraryAdmin admin) {
this.admin = admin;
}
/**
* 借阅书籍
*/
public void borrowBooks(String bookName) {
System.out.println(username + ":我想借一本书, 名为:" + bookName);
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));
pool.execute(() -> {
// 小明向管理员发送请求
admin.receiveRequest(username, bookName, (error, callback) -> {
while (Objects.isNull(callback) && Objects.isNull(error)) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (Objects.nonNull(error)) {
System.out.println("error = " + error);
} else {
System.out.println("成功借阅到书籍");
System.out.println("callback = " + callback);
}
});
});
// 小明开始去做其他事情
doSomething();
pool.shutdown();
}
}
/**
* 定义一个图书管理员
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
@Data
public class LibraryAdmin {
BookFactory bookFactory;
/**
* 1.接收借阅者请求
* 2.管理员查找借阅者需要的书籍
* 3.通知借阅者图书已找到
*
* @return
*/
public void receiveRequest(String username, String bookName, EventCallback<Book> callback) {
Book book = bookFactory.getByName(bookName);
if (Objects.nonNull(book)) {
book.setBorrowStartDate(LocalDateTime.now());
book.setBorrowEndDate(LocalDateTime.now().plusDays(100));
book.setUsername(username);
callback.event(null, new Callback<>(book));
} else {
callback.event(new Error(500, "未查询到指定的书籍"), null);
}
}
}
/**
* 事件回调接口
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
public interface EventCallback<T> {
void event(Error error, Callback<T> callback);
}
/**
* 异常错误通知类
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Error {
Integer status;
String errorMsg;
public Error() {
}
public Error(Integer status, String errorMsg) {
this.status = status;
this.errorMsg = errorMsg;
}
}
/**
* 回调类
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Callback<T> {
T data;
public Callback() {
}
public Callback(T data) {
this.data = data;
}
}
/**
* 图书类
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Book {
/**
* 书名
*/
String bookName;
/**
* 借阅开始时间
*/
LocalDateTime borrowStartDate;
/**
* 借阅结束时间
*/
LocalDateTime borrowEndDate;
/**
* 借阅人
*/
String username;
public Book() {
}
public Book(String bookName) {
this.bookName = bookName;
}
}
/**
* 图书工厂,通过选择指定的书名,来生成对应的书籍
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
public class BookFactory {
/**
* 返回图书
*
* @author xiaofeifei
* @date 2020-02-13
* @updateDate 2020-02-13
* @updatedBy xiaofeifei
* @param
* @return
*/
public Book getByName(String bookName) {
try {
// 随机睡10秒
TimeUnit.SECONDS.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Book(bookName);
}
}
/**
* 业务逻辑处理类
*
* 用户向图书管理员借阅书籍,用户是主动方,首先要与管理员进行交互
*
* @author xiaofeifei
* @date 2020-02-13
* @since
*/
public class BusinessLogicHandler {
public static void main(String[] args) {
BookFactory bookFactory = new BookFactory();
LibraryAdmin admin = new LibraryAdmin();
admin.setBookFactory(bookFactory);
Person person = new Person();
person.setUsername("小明");
// 与图书管理员取得联系
person.connect(admin);
// 开始借书
person.borrowBooks("事件驱动模型");
}
}
运行结果如下:
这样,我们就实现了一个异步的事件驱动模型啦。