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方法等待所有异步操作完成。最后,我们打印出收发邮件的统计数据。


相关文章
|
2月前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
78 1
|
2月前
|
Java API Maven
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
229 10
|
2月前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
11天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
58 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
2月前
|
Java
在Java中实现接口的具体代码示例
可以根据具体的需求,创建更多的类来实现这个接口,以满足不同形状的计算需求。希望这个示例对你理解在 Java 中如何实现接口有所帮助。
92 38
|
22天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
106 13
|
13天前
|
安全 算法 Java
Java CAS原理和应用场景大揭秘:你掌握了吗?
CAS(Compare and Swap)是一种乐观锁机制,通过硬件指令实现原子操作,确保多线程环境下对共享变量的安全访问。它避免了传统互斥锁的性能开销和线程阻塞问题。CAS操作包含三个步骤:获取期望值、比较当前值与期望值是否相等、若相等则更新为新值。CAS广泛应用于高并发场景,如数据库事务、分布式锁、无锁数据结构等,但需注意ABA问题。Java中常用`java.util.concurrent.atomic`包下的类支持CAS操作。
44 2
|
27天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
57 10
|
20天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
56 2