微服務項目->在線oj系統(Java版 - 5)

相信自己,終會成功

微服務代碼:? lyyy-oj: 微服務

目錄

C端代碼

用戶題目接口

?修改后用戶提交代碼(應用版)

?用戶提交題目判題結果

代碼沙箱

1.?代碼沙箱的核心功能

2. 常見的代碼沙箱實現方式

3. 代碼沙箱的關鍵問題與解決方案

4. 你的代碼如何與沙箱交互?

6. 總結

Elasticsearch

RabbitMQ

RabbitMQ 主要功能

RabbitMQ 工作流程示例

典型應用場景


C端代碼

用戶題目接口

從前端接收到數據,判斷是什么語言,如果是Java語言(目前只能進行Java語言的判定)

利用代碼沙箱(下方有介紹),對語言進行判斷

assembleJudgeSubmitDTO:拿到questionId , 從es中查詢題目信息

如果questionES不等于空,

BeanUtil.copyProperties(questionES,judgeSubmitDTO),將questionES復制給 judgeSubmitDTO

否則,從數據庫中查找數據,將查出的數據復制給judgeSubmitDTO

然后將數據存入es中

將從線程池中拿到的數據賦值給judgeSubmitDTO

拼接代碼后進行解析測試用例

步驟說明
questionCaseList.stream()List<QuestionCase>轉為Stream<QuestionCase>,支持鏈式操作
.map(QuestionCase::getInput)提取每個QuestionCase對象的input字段(方法引用,等價于x -> x.getInput()
.toList()Stream<String>收集為不可變List<String>(Java 16+特性)
setInputList/setOutputList最終將輸入/輸出列表設置到判題DTO對象

數據流轉示例

假設原始數據:

List<QuestionCase> questionCaseList = [{"input": "1 2", "output": "3"},{"input": "3 4", "output": "7"}
]

?轉換后結果:

inputList = ["1 2", "3 4"]  // 所有input的集合
outputList = ["3", "7"]      // 所有output的集合
 @Override//后端接收到請求,獲取參數,根據getProgramType判斷用戶提交代碼語言類型//    UserSubmitDTO(用戶提交的數據,包括題目ID、代碼、考試ID等)
//    JudgeSubmitDTO(判題服務需要的數據,包括題目信息、測試用例、用戶代碼等)public R<UserQuestionResultVO> submit(UserSubmitDTO submitDTO) {Integer programType = submitDTO.getProgramType();if(ProgramType.JAVA.getValue().equals(programType)){//按照Java邏輯處理JudgeSubmitDTO judgeSubmitDTO=assembleJudgeSubmitDTO(submitDTO);
//            remoteJudgeService.doJudgeJavaCode(judgeSubmitDTO)return remoteJudgeService.doJudgeJavaCode(judgeSubmitDTO);}throw new ServiceException(ResultCode.FAILED_NOT_SUPPORT_PROGRAM);}private JudgeSubmitDTO assembleJudgeSubmitDTO(UserSubmitDTO submitDTO) {Long questionId = submitDTO.getQuestionId();//orElse,findbyId返回的是Optional對象,并不是數據本身,如果能查出數據,返回數據本身//查不出來數據,返回null// 1. 查詢題目信息(優先ES,不存在則查MySQL并緩存)QuestionES questionES = questionRepository.findById(questionId).orElse(null);JudgeSubmitDTO judgeSubmitDTO=new JudgeSubmitDTO();if(questionES!=null){BeanUtil.copyProperties(questionES,judgeSubmitDTO);}else{Question question = questionMapper.selectById(questionId);BeanUtil.copyProperties(question,judgeSubmitDTO);questionES=new QuestionES();// 2. 組裝 JudgeSubmitDTOBeanUtil.copyProperties(question, questionES);questionRepository.save(questionES);}// 3. 設置用戶信息(從 ThreadLocal 獲取用戶ID)judgeSubmitDTO.setUserId(ThreadLocalUtil.get(Constants.USER_ID,Long.class));judgeSubmitDTO.setExamId(submitDTO.getExamId());judgeSubmitDTO.setProgramType(submitDTO.getProgramType());// 4.拼接用戶代碼和題目主函數judgeSubmitDTO.setUserCode(codeConnect(submitDTO.getUserCode(),questionES.getMainFuc()));// 5. 解析測試用例(從 ES 的 JSON 字符串轉換成 List)List<QuestionCase> questionCaseList = JSONUtil.toList(questionES.getQuestionCase(), QuestionCase.class);List<String> inputList = questionCaseList.stream().map(QuestionCase::getInput).toList();judgeSubmitDTO.setInputList(inputList);List<String> outputList = questionCaseList.stream().map(QuestionCase::getOutput).toList();judgeSubmitDTO.setOutputList(outputList);return judgeSubmitDTO;}

?修改后用戶提交代碼(應用版)

JudgeProducer(使用了RabbitMQ(下方有介紹))

 /*** 將用戶提交的代碼通過RabbitMQ異步發送給判題服務(目前僅支持Java)* @param submitDTO 用戶提交的代碼信息,包含代碼內容、題目ID、編程語言類型等* @return true 提交成功 | 拋出異常 提交失敗(不支持的編程語言)* @throws ServiceException 如果編程語言不支持,拋出業務異常(ResultCode.FAILED_NOT_SUPPORT_PROGRAM)*/@Overridepublic boolean rabbitSubmit(UserSubmitDTO submitDTO) {// 1. 獲取用戶提交的編程語言類型Integer programType = submitDTO.getProgramType();if(ProgramType.JAVA.getValue().equals(programType)){//按照Java邏輯處理, 組裝判題服務需要的DTO(包括代碼、測試用例等信息)JudgeSubmitDTO judgeSubmitDTO=assembleJudgeSubmitDTO(submitDTO);// 通過RabbitMQ生產者將判題任務發送到消息隊列(異步處理)
//             把參數給rabbitmq,但是沒執行判題結果,目前實現是同步調用遠程服務judgeProducer.produceMsg(judgeSubmitDTO);// 返回true表示消息已成功提交到隊列(注意:不表示判題已完成)return true;}throw new ServiceException(ResultCode.FAILED_NOT_SUPPORT_PROGRAM);}
@Component
//@Component:將該類標記為 Spring 組件,由 Spring 容器管理
@Slf4j
public class JudgeProducer {@Autowiredprivate RabbitTemplate rabbitTemplate;public void produceMsg(JudgeSubmitDTO judgeSubmitDTO) {try {
//            使用 RabbitTemplate 向 RabbitMQ
//            發送消息消息內容是 JudgeSubmitDTO(判題提交數據傳輸對象)
//            發送到名為 OJ_WORK_QUEUE 的隊列rabbitTemplate.convertAndSend(RabbitMQConstants.OJ_WORK_QUEUE, judgeSubmitDTO);} catch (Exception e) {log.error("生產者發送消息異常", e);throw new ServiceException(ResultCode.FAILED_RABBIT_PRODUCE);}}
}

?用戶提交題目判題結果

  /*** 根據考試ID、題目ID和時間戳查詢用戶的判題結果* @param examId 考試ID* @param questionId 題目ID* @param currentTime 提交時間標識(用于區分同一題目的多次提交)* @return UserQuestionResultVO 包含判題狀態、執行結果、用例詳情等*/@Overridepublic UserQuestionResultVO exeResult(Long examId, Long questionId, String currentTime) {//把結果獲取出來// 1. 從ThreadLocal中獲取當前用戶ID(基于登錄上下文)Long userId = ThreadLocalUtil.get(Constants.USER_ID, Long.class);// 2. 查詢數據庫獲取用戶提交記錄UserSubmit userSubmit = userSubmitMapper.selectCurrentUserSubmit(userId, questionId, examId, currentTime);// 3. 構建返回VO對象UserQuestionResultVO resultVO = new UserQuestionResultVO();// 4. 判題結果不存在的情況(可能還在判題中)if (userSubmit == null) {resultVO.setPass(QuestionResType.IN_JUDGE.getValue()); // 設置狀態為"判題中"}// 5. 存在判題結果else {resultVO.setPass(userSubmit.getPass());resultVO.setExeMessage(userSubmit.getExeMessage());if (StrUtil.isNotEmpty(userSubmit.getCaseJudgeRes())) {resultVO.setUserExeResultList(JSON.parseArray(userSubmit.getCaseJudgeRes(), UserExeResult.class));}}return resultVO;}

代碼沙箱

代碼沙箱(Code Sandbox)是一種安全隔離的執行環境,用于運行不受信任的代碼(如用戶提交的編程題答案),防止惡意代碼影響主系統。在在線判題系統(Online Judge)中,代碼沙箱是核心組件之一。

1.?代碼沙箱的核心功能

功能

說明

安全隔離

防止用戶代碼破壞主機(如刪除文件、無限循環、占用資源)。

資源限制

限制 CPU、內存、執行時間,避免惡意代碼耗盡系統資源。

輸入/輸出控制

提供標準輸入(測試用例),捕獲標準輸出/錯誤,與判題系統交互。

多語言支持

支持 Java、Python、C++ 等語言的編譯和運行。

錯誤處理

捕獲運行時異常、編譯錯誤,并返回友好提示。

2. 常見的代碼沙箱實現方式

1.基于 Docker 的沙箱

原理:每個用戶提交的代碼在一個臨時 Docker 容器中運行,運行后銷毀。

優點

強隔離性(進程、文件系統、網絡均隔離)。

可限制 CPU、內存等資源(通過?cgroups)。

示例流程

用戶提交代碼 → 判題系統接收。

生成臨時 Docker 容器,掛載代碼文件。

在容器內編譯/運行代碼,傳入測試用例。

捕獲輸出,對比預期結果。

銷毀容器。

2. 基于 JVM 沙箱(Java 專用)

原理:利用 Java 的?SecurityManager?或字節碼修改(如 ASM)限制敏感操作。

優點

輕量級,啟動快。

適合純 Java 判題場景。

缺點

無法完全隔離系統調用(如?System.exit())。

需要自定義安全策略。

3. 第三方沙箱服務

示例

Judge0:開源的在線判題沙箱(支持 60+ 語言)。

Piston:輕量級多語言執行引擎。

優點:無需自行維護沙箱環境。

3. 代碼沙箱的關鍵問題與解決方案

問題

解決方案

惡意代碼

使用 Docker 隔離,限制系統調用(如?forkexec)。

無限循環

設置超時機制(如 Linux 的?timeout?命令)。

內存溢出

通過?-Xmx?限制 JVM 內存,或 Docker?--memory?限制容器內存。

文件系統安全

Docker 使用只讀文件系統,或臨時掛載空目錄。

網絡隔離

禁用容器網絡(--network none)。

4. 你的代碼如何與沙箱交互?

執行流程

用戶提交代碼 → 你的服務組裝?JudgeSubmitDTO(題目ID、代碼、測試用例等)。

通過 Feign 調用判題服務(remoteJudgeService.doJudgeJavaCode)。

判題服務將代碼發送到?代碼沙箱?執行。

沙箱返回結果(通過/失敗、錯誤信息、用時等)。

你的服務接收結果并返回給用戶。

6. 總結

代碼沙箱?是判題系統的核心,確保安全性和穩定性。

推薦方案

小型系統:用?Docker?快速實現。

大型系統:結合?Kubernetes?管理沙箱集群。

擴展方向

支持更多語言(Python、C++)。

分布式判題(提高并發能力)。

為什么需要沙箱?

安全隔離:防止用戶代碼破壞宿主系統。

資源控制:限制CPU/內存使用,避免惡意代碼耗盡資源。

環境一致性:確保每次執行都在干凈的環境中運行。


Elasticsearch

官方網站:

Elastic Docs | Elastic

Elasticsearch(簡稱 ES)是一個開源的分布式 搜索和分析引擎,基于 Apache Lucene 構建,專為處理海量數據設計,支持近實時(NRT, Near Real-Time)搜索。

優點

高性能搜索,支持復雜查詢(全文檢索、模糊匹配、聚合分析)。

水平擴展能力強,適合大數據場景。

生態完善(ELK Stack、APM、SIEM 等)。

缺點

不支持事務(不適合金融級一致性要求場景)。

資源消耗較高(尤其是內存)。

學習曲線較陡(需理解分詞、映射、集群管理等)


RabbitMQ

RabbitMQ 是一個開源的?消息代理(Message Broker),實現了?AMQP(Advanced Message Queuing Protocol)?協議,用于在分布式系統中存儲、轉發消息。

核心角色:生產者(Producer)→?RabbitMQ?→ 消費者(Consumer)

典型場景:異步任務處理、應用解耦、流量削峰、分布式系統通信。

概念說明
Producer消息生產者,發送消息到 Exchange
Consumer消息消費者,從 Queue 接收消息
Exchange消息路由組件,決定消息投遞到哪些 Queue(類型:Direct、Fanout、Topic、Headers)
Queue存儲消息的緩沖區,消費者從中訂閱消息
BindingExchange 和 Queue 的綁定規則(如路由鍵 Routing Key)
Channel輕量級連接(復用 TCP 連接,減少開銷)
Virtual Host虛擬隔離環境(類似命名空間,不同 vhost 資源互不干擾)

RabbitMQ 主要功能

消息路由(Exchange Types)

Direct Exchange
→ 精確匹配?Routing Key,消息投遞到完全匹配的 Queue。

// 示例:日志級別路由(error、warning、info)
channel.queueBind("error_queue", "logs_exchange", "error");

Fanout Exchange
→ 廣播模式,消息發送到所有綁定的 Queue(忽略 Routing Key)。

// 示例:新聞通知廣播
channel.exchangeDeclare("news", BuiltinExchangeType.FANOUT);

?Topic Exchange
→ 通配符匹配?Routing Key*?匹配一個詞,#?匹配多個詞)。

// 示例:訂單路由(order.create、order.payment.success)
channel.queueBind("queue_payment", "orders", "order.payment.*");

?Headers Exchange
→ 基于消息頭(Headers)匹配,不依賴 Routing Key(性能較低,較少使用)。

?消息可靠性

消息確認(ACK/NACK)
→ 消費者處理成功后發送?ACK,失敗時?NACK(可配置重試或進入死信隊列)。

channel.basicConsume(queue, false, consumer); // 手動ACK
channel.basicAck(deliveryTag, false); // 確認處理成功

?持久化(Persistence)
→ Exchange、Queue、消息均可持久化到磁盤,防止服務重啟丟失。

// 聲明持久化隊列
channel.queueDeclare("task_queue", true, false, false, null);

?死信隊列(DLX)
→ 處理失敗或超時的消息可轉發到死信隊列,用于異常監控和重試。

Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", "dlx_exchange");
channel.queueDeclare("normal_queue", false, false, false, args);

高級特性

TTL(Time-To-Live)
→ 設置消息或隊列的過期時間(超時未消費則自動刪除)。

// 消息級別TTL
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().expiration("60000") // 60秒過期.build();
channel.basicPublish(exchange, routingKey, props, message.getBytes());

優先級隊列(Priority Queue)
→ 消息按優先級消費(需隊列聲明時支持)。

Map<String, Object> args = new HashMap<>();
args.put("x-max-priority", 10); // 最大優先級為10
channel.queueDeclare("priority_queue", false, false, false, args);

?集群與鏡像隊列
→ 支持多節點集群,鏡像隊列(Mirrored Queue)實現高可用。

RabbitMQ 工作流程示例

典型應用場景

  1. 異步任務處理
    → 用戶注冊后異步發送郵件/短信。

  2. 應用解耦
    → 訂單系統與庫存系統通過消息隊列通信。

  3. 流量削峰
    → 秒殺請求先寫入隊列,后端按能力消費。

  4. 日志收集
    → 多個服務發送日志到統一隊列,由消費者存儲到ES/數據庫。

?對比其他消息隊列

RabbitMQKafkaRocketMQ
協議AMQP自定義協議自定義協議
吞吐量中等(萬級TPS)高(百萬級TPS)高(十萬級TPS)
延遲低(毫秒級)中(依賴批量)
適用場景業務消息、實時處理日志流、大數據金融級事務消息

RabbitMQ 是輕量級、高可用的消息中間件,適合需要可靠消息傳遞的分布式系統。通過靈活的路由規則和豐富的特性,平衡了性能與功能需求?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/80622.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/80622.shtml
英文地址,請注明出處:http://en.pswp.cn/web/80622.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue3 Element Plus 中el-table-column索引使用問題

在 Element Plus 的 el-table 組件中&#xff0c;使用 scope.index 是不準確的。正確的索引屬性應該是 scope.$index。你的代碼需要調整為&#xff1a; vue 復制 下載 <el-button type"primary" size"default" text click"onModifyClick(scope…

Ubuntu20.04下使用dpkg方式安裝WPS后,將WPS改為中文界面方法

Ubuntu20.04下使用dpkg方式安裝WPS后&#xff0c;將WPS改為中文界面方法 說明方法 說明 Ubuntu20.04下使用dpkg方式安裝WPS后&#xff0c;打開WPS后&#xff0c;發現界面是英文的&#xff0c;如有需要可以按照下面的方法將其改為中文界面。 方法 cd /opt/kingsoft/wps-offic…

【??HTTPS基礎概念與原理?】??HTTPS vs HTTP:為什么現代網站必須用HTTPS?

以下是關于 HTTPS vs HTTP 的詳細對比分析&#xff0c;涵蓋安全性、性能差異及SEO影響&#xff0c;幫助您全面理解為何現代網站必須采用HTTPS&#xff1a; 一、安全性對比&#xff1a;HTTPS 如何解決 HTTP 的致命缺陷 1. HTTP 的安全隱患 ? 明文傳輸&#xff1a;HTTP 數據以明…

算法刷題(Java與Python)1.二分查找

目錄 二分查找 思路 總體 細節 問題一&#xff0c;為什么循環的條件是left<right ,為什么要有等號呢 問題二&#xff0c;為什么中間值是left (right - left) / 2 問題三&#xff0c;為什么最后返回的是左邊的值呢 情況 1&#xff1a;target 存在于數組中 情況 2&a…

芯片生態鏈深度解析(二):基礎設備篇——人類精密制造的“巔峰對決”

【開篇&#xff1a;設備——芯片工業的“劍與盾”】 當ASML的EUV光刻機以每秒5萬次激光脈沖在硅片上雕刻出0.13nm精度的電路&#xff08;相當于在月球表面精準定位一枚二維碼&#xff09;&#xff0c;當國產28nm光刻機在華虹產線實現“從0到1”的突破&#xff0c;這場精密制造…

MongoTemplate 基礎使用幫助手冊

前言 MongoDB 是一種流行的 NoSQL 數據庫&#xff0c;適合存儲大量的非結構化數據。MongoTemplate 是 Spring Data MongoDB 中的一個核心組件&#xff0c;它提供了一組豐富的 API 來與 MongoDB 進行交互。它封裝了許多常見的數據庫操作&#xff0c;使開發者能夠輕松執行 CRUD 操…

psotgresql18 源碼編譯安裝

環境&#xff1a; 系統&#xff1a;centos7.9 數據庫&#xff1a;postgresql18beta1 #PostgreSQL 18 已轉向 DocBook XML 構建體系&#xff08;SGML 未來將被棄用&#xff09;。需要安裝 XML 工具鏈&#xff0c;如下&#xff1a; yum install -y docbook5-style-xsl libxsl…

C++編程起步項目

員工信息管理系統 需求 Employee.h #pragma once#include<iostream> #include<string>using namespace std;class Employee { public:int id; // 編號string name; // 姓名string position; // 崗位int deptId; // 部門編號Employee();Employee(int id, string n…

Linux的MySQL頭文件和找不到頭文件問題解決

頭文件 #include <iostream> #include <mysql_driver.h> #include <mysql_connection.h> #include <cppconn/statement.h> #include <cppconn/resultset.h> #include <cppconn/prepared_statement.h> #include <cppconn/exception.h&g…

[ linux-系統 ] 命令行參數 | 環境變量

命令行參數 命令行參數是指用戶在啟動程序時通過命令行傳遞給程序的參數。這些參數可以用于控制程序的行為、傳遞輸入數據或配置選項。 在 C/C 中&#xff0c;命令行參數通過 main 函數的參數傳遞 命令行參數列表 argc:參數的個數 argv[]&#xff1a;參數的清單 為什么要…

新書速覽|鴻蒙HarmonyOS NEXT開發之路 卷2:從入門到應用篇

《鴻蒙HarmonyOS NEXT開發之路 卷2&#xff1a;從入門到應用篇》 01 本書內容 《鴻蒙HarmonyOS NEXT開發之路 卷2&#xff1a;從入門到應用篇》是一本深度聚焦HarmonyOS NEXT應用開發的全方位指導書&#xff0c;內容遵循由淺入深的原則展開。全書分為基礎知識、應用開發進階和…

經典密碼學和現代密碼學的結構及其主要區別(1)凱撒密碼——附py代碼

密碼學是一門通過使用代碼和密碼來保護信息的藝術與科學&#xff0c;其歷史可以追溯到數千年前。古典密碼學代表了這一古老學科早期的篇章。早在計算機和現代加密算法出現之前&#xff0c;歷史上的各個文明就依靠巧妙的方法來保護機密、安全通信以及獲取戰略優勢。 古典密碼學…

Python60日基礎學習打卡D30

回顧&#xff1a; 導入官方庫的三種手段導入自定義庫/模塊的方式導入庫/模塊的核心邏輯&#xff1a;找到根目錄&#xff08;python解釋器的目錄和終端的目錄不一致&#xff09; # 直接導入 from random import randint print(randint(1, 10)) # 導入自定義庫 import module m…

Linux利用多線程和線程同步實現一個簡單的聊天服務器

1. 概述 本文實現一個基于TCP/IP的簡單多人聊天室程序。它包含一個服務器端和一個客戶端&#xff1a;服務器能夠接收多個客戶端的連接&#xff0c;并將任何一個客戶端發來的消息廣播給所有其他連接的客戶端&#xff1b;客戶端則可以連接到服務器&#xff0c;發送消息并接收來自…

ubuntu系統 | dify+ollama+deepseek搭建本地應用

1、安裝 Ollama 下載并安裝 Ollama (llm) wangqiangwangqiang:~$ curl -fsSL https://ollama.ai/install.sh | bash >>> Installing ollama to /usr/local >>> Downloading Linux amd64 bundle0.3% curl -fsSL https://ollama.ai/install.sh &#xff08;下…

從紙質契約到智能契約:AI如何改寫信任規則與商業效率??——從智能合約到監管科技,一場顛覆傳統商業邏輯的技術革命

一、傳統合同的“低效困境”&#xff1a;耗時、昂貴、風險失控 近年來&#xff0c;全球商業環境加速向數字化轉型&#xff0c;但合同管理卻成為企業效率的“阿喀琉斯之踵”。據國際商會&#xff08;International Chamber of Commerce&#xff09;數據顯示&#xff0c;全球企業…

【機器學習|學習筆記】基于生成對抗網絡的孿生框架(GAN-based Siamese framework,GSF)詳解,附代碼。

【機器學習|學習筆記】基于生成對抗網絡的孿生框架(GAN-based Siamese framework,GSF)詳解,附代碼。 【機器學習|學習筆記】基于生成對抗網絡的孿生框架(GAN-based Siamese framework,GSF)詳解,附代碼。 文章目錄 【機器學習|學習筆記】基于生成對抗網絡的孿生框架(G…

UEFI Spec 學習筆記---33 - Human Interface Infrastructure Overview---33.2.6 Strings

33.2.6 Strings UEFI 環境中的 string 是使用 UCS-2 格式定義&#xff0c;每個字符由 16bit 數據表示。對于用戶界面&#xff0c;strings 也是一種可以安裝到 HIIdatabase 的一種數據。 為了本土化&#xff0c;每個 string 通過一個唯一標識符來識別&#xff0c;而每一個標識…

Stable Diffusion 學習筆記02

模型下載網站&#xff1a; 1&#xff0c;LiblibAI-哩布哩布AI - 中國領先的AI創作平臺 2&#xff0c;Civitai: The Home of Open-Source Generative AI 模型的安裝&#xff1a; 將下載的sd模型放置在sd1.5的文件內即可&#xff0c;重啟客戶端可用。 外掛VAE模型&#xff1a…

并發編程(5)

拋異常時會釋放鎖。 當線程在 synchronized 塊內部拋出異常時&#xff0c;會自動釋放對象鎖。 public class ExceptionUnlockDemo {private static final Object lock new Object();public static void main(String[] args) {Thread t1 new Thread(() -> {synchronized …