Java多线程 Guarded Suspension设计模式

yizhihongxing

Java多线程中的Guarded Suspension设计模式利用了等待-通知机制来实现线程间的协作。该模式常用于多个线程之间共享资源的情况下,其中一个线程需要等待另一个线程的结果才能进行后续操作。下面是Guarded Suspension模式的详细攻略和两个示例说明。

Guarded Suspension设计模式

Guarded Suspension设计模式中有以下三个角色:

  1. Guarded Object:受保护的对象,用于提供线程等待和通知机制。
  2. Guarded Action:受保护的操作,用于实现Guarded Object中的方法,包含等待和唤醒等关键逻辑。
  3. Guarded Suspension模式:用于将Guarded Object和Guarded Action连接起来的设计模式。

Guarded Object是一个类,其包含了等待和唤醒等方法,如wait()、notify()和notifyAll()等。Guarded Action用于实现Guarded Object中的方法,其中使用了synchronized关键字进行线程同步,以便在Guarded Object被唤醒时执行相应的操作。

示例一

下面我们将介绍一个简单的示例,实现了Guarded Suspension设计模式的基本原理。

public class GuardedObject {
    private Object response;

    public synchronized Object get() throws InterruptedException {
        while(response == null) {
            wait();
        }
        return response;
    }

    public synchronized void put(Object response) {
        this.response = response;
        notifyAll();
    }
}

public class GuardedAction {
    public void execute() throws InterruptedException {
        GuardedObject guardedObject = new GuardedObject();
        // 模拟后台任务
        new Thread(() -> {
            try {
                String result = "Hello World";
                guardedObject.put(result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        // 获取结果
        Object result = guardedObject.get();
        System.out.println("Result: " + result);
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            GuardedAction action = new GuardedAction();
            action.execute();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

Result: Hello World

在这个示例中,GuardedObject对象提供了get()和put()两个方法,get()方法用于获取结果,而put()方法用于向GuardedObject对象中存储结果。GuardedAction对象调用execute()方法时,会在另一个线程中执行后台任务,并将结果存储在GuardedObject对象中。execute()方法会在当前线程等待,直到GuardedObject对象中有结果被存储,之后再返回结果。

示例二

接下来,我们将介绍一个更为实用的示例,用于解决一个订单支付的问题,其中包括订单信息的缓存和支付结果的通知。以下是示例的代码:

public class Order {
    private String orderId;
    private double amount;
    private boolean isFinished;

    // 构造方法和getter/setter方法省略
}

public class OrderCache {
    private Map<String, Order> cache = new ConcurrentHashMap<>();

    public void addOrder(Order order) {
        cache.put(order.getOrderId(), order);
    }

    public Order getOrder(String orderId) throws InterruptedException {
        Order order = cache.get(orderId);
        if(order == null) {
            GuardedObject guardedObject = new GuardedObject();
            synchronized (guardedObject) {
                cache.put(orderId, null);
                OrderServiceImpl.payOrder(orderId, new PaymentCallback() {
                    @Override
                    public void onComplete(boolean success) {
                        Order order = cache.get(orderId);
                        if(order == null) {
                            order = new Order(orderId, 0, false);
                            cache.put(orderId, order);
                        }
                        order.setFinished(success);
                        guardedObject.put(order);
                    }
                });
                return (Order) guardedObject.get();
            }
        }
        return order;
    }
}

public class OrderServiceImpl {
    public static void payOrder(String orderId, PaymentCallback callback) {
        new Thread(() -> {
            try {
                Thread.sleep(5000);
                callback.onComplete(true);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

public interface PaymentCallback {
    void onComplete(boolean success);
}

public class Main {
    public static void main(String[] args) {
        OrderCache orderCache = new OrderCache();
        try {
            Order order = orderCache.getOrder("20210716-001");
            System.out.println("Order Id: " + order.getOrderId() + ", Finished: " + order.isFinished());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,OrderCache对象用于缓存订单信息,并提供了getOrder()方法来获取订单信息。如果订单信息尚未缓存,系统会调用OrderServiceImpl对象的payOrder()方法进行支付,并使用GuardedObject对象来等待支付结果。当支付结果返回后,系统会存储结果到实际的Order对象中,并使用GuardedObject对象来通知等待的线程获取结果。

运行结果如下:

Order Id: 20210716-001, Finished: true

在上面的示例中,GuardedObject对象的put()方法会将支付结果存储到新创建的Order对象中,而get()方法会将这个Order对象返回。这样,就可以通过Guarded Suspension设计模式来实现订单支付的功能,提供了较好的可扩展性和可维护性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程 Guarded Suspension设计模式 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Java实现前端jsencrypt.js加密后端解密的示例代码

    下面是实现Java实现前端jsencrypt.js加密后端解密的完整攻略: 一、前言 在前后端分离架构中,涉及到传输敏感信息时通常会进行加密处理。在前端,我们可以使用jsencrypt.js这样的JS库进行加密操作,但将加密后的数据发送到后端后,我们需要使用Java等语言进行解密操作。 因此,本文将讲解如何使用Java实现前端jsencrypt.js加密后端…

    Java 2023年5月19日
    00
  • Spring框架读取property属性文件常用5种方法

    非常感谢你对Spring框架的关注。Spring框架支持多种读取属性文件的方式,其中最常用的五种方法有以下: 方法1:通过@Value注解获取property文件中的属性值 在Spring框架中,可以通过@Value注解快速获取配置文件中的属性和环境变量的值。首先要在Spring配置文件中进行配置,在标签中添加如下配置: <context:proper…

    Java 2023年5月31日
    00
  • java文件复制代码片断(java实现文件拷贝)

    Java文件复制是Java中常用的操作之一,我们通常利用类库中的FileInputStream 和 FileOutputStream来实现文件拷贝。下面是Java文件复制代码片段的完整攻略: 步骤一:创建输入输出流对象 首先要创建输入输出流对象,读取原文件并将文件写入指定文件。这里我们使用Java中的FileInputStream和FileOutputStr…

    Java 2023年5月31日
    00
  • 详解Java的Struts框架中注释的用法

    下面我来为您详细讲解Java的Struts框架中注释的用法。 简介 在Java的Struts2框架中,注释的用法很重要。注释提供了一种添加元数据的方式,可以提供更多的关于类、方法和字段的信息。通常情况下,注释会在类或方法上方以及变量定义前面进行添加。 注释的用途 1. 将文档内容嵌入到源代码 在Struts2的框架中,注释还可以通过特殊的开关进行预处理和编译…

    Java 2023年5月20日
    00
  • 这么优雅的Java ORM没见过吧!

    首先,我们需要了解Java ORM的概念。ORM(Object Relational Mapping)是指对象关系映射,是一种将面向对象的程序与关系型数据库之间进行数据转换的技术。Java中有很多ORM框架,如Hibernate、MyBatis、JPA等,它们可以帮助开发者更加方便、高效地访问数据库。 接下来,我们来了解一款优雅的Java ORM框架——Jo…

    Java 2023年5月20日
    00
  • 深入理解Mybatis中的resultType和resultMap

    深入理解Mybatis中的resultType和resultMap Mybatis是一个流行的ORM框架,它的核心是将Java对象映射到数据库中的表格。在Mybatis中,resultType和resultMap是最重要的两个属性,用于将SQL查询结果映射为Java对象。 resultType resultType是一个简单的属性,它指定了SQL查询返回值的…

    Java 2023年5月20日
    00
  • java读取文件显示进度条的实现方法

    Java读取文件并显示进度条的实现方法可以分为以下几步: 步骤一:获取文件大小 File file = new File("文件路径"); long fileSize = file.length(); 步骤二:读取文件并更新进度条 FileInputStream fileInputStream = new FileInputStream(…

    Java 2023年5月20日
    00
  • Spring Boot 文件上传与下载的示例代码

    下面是 “Spring Boot 文件上传与下载的示例代码”的完整攻略,包含了两条示例。 Spring Boot 文件上传与下载的示例代码 文件上传 1. 准备工作 在pom.xml中添加依赖: <dependency> <groupId>org.springframework.boot</groupId> <art…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部