Java web 开发涉及多线程和锁定的应用场景有哪些?(邮件发送和接收示例)

简介: Java web 开发中,有一些场景需要用到多线程和锁定,以提高性能、保证数据一致性或实现特定的功能,多线程和锁定提升网站性能、保障数据安全或实现复杂功能的重要技术手段。

{E0AD6CBA-E530-B12D-9A99-499D8F796559}.pngJava web 开发中,有一些场景需要用到多线程和锁定,以提高性能、保证数据一致性或实现特定的功能,多线程和锁定提升网站性能、保障数据安全或实现复杂功能的重要技术手段。以下是一些常见的应用场景:

  • 异步处理:为了避免耗时操作阻塞主线程或消耗过多资源,可以利用多线程技术异步执行这些操作,如发送邮件、调用外部接口、生成报告等。Java提供了ExecutorService、CompletableFuture等工具类来管理线程池,并通过Future、Callback等方式来获取异步结果。
  • 并发访问共享资源:当多个线程同时访问同一个共享资源,如数据库、文件、缓存等,就需要使用锁定技术来确保数据的一致性和完整性。Java提供了synchronized关键字和Lock接口(如ReentrantLock)来实现锁定机制,并要注意避免死锁、活锁、饥饿等问题。
  • 读写分离:当一个共享资源的读操作远远多于写操作,且写操作不影响读操作的正确性时,可以使用读写分离技术来提高并发性能。Java提供了ReadWriteLock接口(如ReentrantReadWriteLock)来实现读写锁定机制,允许多个线程并发读取,但只允许一个线程独占写入。
  • 条件同步:当一个线程需要在满足某个条件后才能继续执行时,可以使用条件同步技术来实现线程间的协作。Java提供了Object.wait() / notify() / notifyAll()方法, 或者 Lock.newCondition() / await() / signal() / signalAll()方法, 或者 CountDownLatch / CyclicBarrier / Semaphore / Exchanger 等工具类, 来创建和管理条件变量,并在合适的时机进行通知或等待。

下面代码采用多线程技术实现邮件发送和接收:

importjavax.mail.*;
importjavax.mail.internet.InternetAddress;
importjavax.mail.internet.MimeMessage;
importjava.util.Properties;
importjava.util.concurrent.*;
publicclassAsyncEmailSender {
privatestaticfinalStringSMTP_SERVER="smtp.163.com";// 邮箱服务器privatestaticfinalStringUSERNAME="your_email@163.com";// 邮箱账号privatestaticfinalStringPASSWORD="your_password";// 邮箱密码privatestaticfinalintNUM_THREADS=10;
privatestaticfinalExecutorServiceexecutor=Executors.newFixedThreadPool(NUM_THREADS);
privatestaticfinalStringPROXY_HOST="www.16yun.cn";// 代理服务器privatestaticfinalintPROXY_PORT=31111;// 代理yprivatestaticfinalStringPROXY_USERNAME="16YUN";// 代理用户名privatestaticfinalStringPROXY_PASSWORD="16IP";// 代理密码privatestaticfinalPropertiesPROXY_PROPERTIES=newProperties() {{
put("http.proxyHost", PROXY_HOST);
put("http.proxyPort", String.valueOf(PROXY_PORT));
put("https.proxyHost", PROXY_HOST);
put("https.proxyPort", String.valueOf(PROXY_PORT));
put("http.proxyUser", PROXY_USERNAME);
put("http.proxyPassword", PROXY_PASSWORD);
put("https.proxyUser", PROXY_USERNAME);
put("https.proxyPassword", PROXY_PASSWORD);
        }};
privatestaticintnumSent=0;
privatestaticintnumReceived=0;
publicstaticvoidmain(String[] args) throwsInterruptedException, ExecutionException {
CompletableFuture<Void>sendFuture=CompletableFuture.runAsync(() -> {
sendEmail("recipient@example.com", "Test Subject", "Test Body");
// 在此加入更多调用sendEmail方法的代码,以发送更多邮件        }, executor);
CompletableFuture<Void>receiveFuture=CompletableFuture.runAsync(() -> {
receiveEmail("inbox"); // 接收收件箱中的邮件        }, executor);
CompletableFuture<Void>allFutures=CompletableFuture.allOf(sendFuture, receiveFuture);
allFutures.get();
executor.shutdown();
System.out.println("Sent "+numSent+" emails");
System.out.println("Received "+numReceived+" emails");
    }
publicstaticvoidsendEmail(Stringrecipient, Stringsubject, Stringbody) {
// Set the properties of the SMTP serverPropertiesprops=newProperties(PROXY_PROPERTIES);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", SMTP_SERVER);
props.put("mail.smtp.port", "25"); // 163邮箱使用的是25号端口// Create a new session with the SMTP serverSessionsession=Session.getInstance(props, newjavax.mail.Authenticator() {
protectedPasswordAuthenticationgetPasswordAuthentication() {
returnnewPasswordAuthentication(USERNAME, PASSWORD);
            }
        });
try {
// Create a new messageMessagemessage=newMimeMessage(session);
message.setFrom(newInternetAddress(USERNAME));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
message.setSubject(subject);
message.setText(body);
// Send the messageTransport.send(message);
synchronized (AsyncEmailSender.class) {
numSent++;
            }
        } catch (MessagingExceptione) {
        }

在这个示例中,我们使用了一个ExecutorService来创建一个线程池,构造函数的参数指定了线程池中的线程数量。使用CompletableFuture.runAsync方法将sendEmail和receiveEmail方法异步执行,在sendEmail和receiveEmail方法中,我们使用Proxy_properties将代理IP的配置添加到Properties对象中,实现了服务器IP的隐藏,在其中的sendEmail方法中,我们加入了一个synchronized块以确保numSent变量的所有操作都是同步的,避免出现竞争条件。在receiveEmail方法中,我们同样加入了一个synchronized块,以确保numReceived变量的所有操作都是同步的。在main方法中,我们调用了CompletableFuture.allOf方法等待所有异步操作完成。最后,我们打印出收发邮件的统计数据。


相关文章
|
7月前
|
人工智能 算法 Java
Java与AI驱动区块链:构建智能合约与去中心化AI应用
区块链技术和人工智能的融合正在开创去中心化智能应用的新纪元。本文深入探讨如何使用Java构建AI驱动的区块链应用,涵盖智能合约开发、去中心化AI模型训练与推理、数据隐私保护以及通证经济激励等核心主题。我们将完整展示从区块链基础集成、智能合约编写、AI模型上链到去中心化应用(DApp)开发的全流程,为构建下一代可信、透明的智能去中心化系统提供完整技术方案。
475 3
|
7月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
633 8
|
8月前
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
1364 12
|
8月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
1403 1
|
Java 开发工具 git
Java开发初级6.24.3
5.在Git使用过程中,进行Git配置的操作命令是哪个() A. config B. config -g C. config -a D. git config 相关知识点: 在git中,经常使用git config 命令用来配置git的配置文件,git配置级别主要有:仓库级别 local 【优先级最高】、用户级别 global【优先级次之】、系统级别 system【优先级最低】 正确答案:D 10.RDBMS是什么? A. Rela Database Management Systems B. Relational Database Management Systems C. Relation
279 0
|
SQL 前端开发 JavaScript
Java开发初级6.24.2
3.Java网站src/main/java目录保存的是什么资源? A. Java源代码文件 B. 测试代码 C. JavaScript、CSS等文件 D. 图片资源 正确答案:A 4.什么是索引Index? A. SQL数据库里的表管理工具 B. SQL数据库里的查询工具 C. SQL数据库里的目录工具 D. SQL数据库用来加速数据查询的特殊的数据结构 正确答案:D
347 0
|
Java
Java开发初级6.24.1
1.下面关于泛型的描述中错误的一项是? A. “? extends 类”表示设置泛型上限 B. “? super 类”表示设置泛型下限 C. 利用“?”通配符可以接收全部的泛型类型实例,但却不可修改泛型属性内容 D. 如果类在定义时使用了泛型,则在实例化类对象时需要设置相应的泛型类型,否则程序将无法编译通过 相关知识点: https://edu.aliyun.com/course/35 正确答案:D 2.下列选项中属于SVN中控制鉴权用户访问版本库的权限默认权限的是() A. write B. read C. none D. null 相关知识点: auth-access:取值范围为"writ
385 0
|
Java 开发工具 git
Java开发初级6.23.3
5.在Git使用过程中,进行Git配置的操作命令是哪个() A. config B. config -g C. config -a D. git config 相关知识点: 在git中,经常使用git config 命令用来配置git的配置文件,git配置级别主要有:仓库级别 local 【优先级最高】、用户级别 global【优先级次之】、系统级别 system【优先级最低】 正确答案:D 10.RDBMS是什么? A. Rela Database Management Systems B. Relational Database Management Systems C. Relation
222 0
|
SQL 前端开发 JavaScript
Java开发初级6.23.2
3.Java网站src/main/java目录保存的是什么资源? A. Java源代码文件 B. 测试代码 C. JavaScript、CSS等文件 D. 图片资源 正确答案:A 4.什么是索引Index? A. SQL数据库里的表管理工具 B. SQL数据库里的查询工具 C. SQL数据库里的目录工具 D. SQL数据库用来加速数据查询的特殊的数据结构 正确答案:D
385 0
|
Java
Java开发初级6.23.1
1.下面关于泛型的描述中错误的一项是? A. “? extends 类”表示设置泛型上限 B. “? super 类”表示设置泛型下限 C. 利用“?”通配符可以接收全部的泛型类型实例,但却不可修改泛型属性内容 D. 如果类在定义时使用了泛型,则在实例化类对象时需要设置相应的泛型类型,否则程序将无法编译通过 相关知识点: https://edu.aliyun.com/course/35 正确答案:D 2.下列选项中属于SVN中控制鉴权用户访问版本库的权限默认权限的是() A. write B. read C. none D. null 相关知识点: auth-access:取值范围为"writ
299 0