当前位置: 首页 > wzjs >正文

网站咋做外贸营销网站

网站咋做,外贸营销网站,网站怎么建设原始站点,wordpress虚拟主机加速思维导图: 在 Spring Boot 里,默认情况下 Bean 是单例的。单例 Bean 意味着在整个应用程序上下文里只有一个实例。要是这个单例 Bean 有状态(也就是包含实例变量),而且多个线程同时对这些实例变量进行读写操作&#xf…

 思维导图:

  在 Spring Boot 里,默认情况下 Bean 是单例的。单例 Bean 意味着在整个应用程序上下文里只有一个实例。要是这个单例 Bean 有状态(也就是包含实例变量),而且多个线程同时对这些实例变量进行读写操作,就可能产生线程安全问题。下面是一个具体的示例。


1. 创建 Spring Boot 项目

可以使用 Spring Initializr(https://start.spring.io/)创建一个包含 Spring Web 依赖的 Spring Boot 项目。

2. 定义有状态的单例 Bean

创建一个 CounterService 类,它有一个实例变量 count,还有两个方法分别用于增加计数和获取计数。

package com.example.demo.service;import org.springframework.stereotype.Service;@Service
public class CounterService {private int count = 0;public void increment() {try {// 模拟耗时操作,放大线程安全问题Thread.sleep(1);} catch (InterruptedException e) {Thread.currentThread().interrupt();}count++; // 非原子操作,多线程下易出现问题}public int getCount() {return count;}
}

 3. 创建控制器来调用 Bean

创建一个 CounterController 类,它会注入 CounterService中的 Bean,并且提供两个端点,一个用于增加计数,另一个用于获取计数。

package com.example.demo.controller;import com.example.demo.service.CounterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class CounterController {@Autowiredprivate CounterService counterService;@GetMapping("/increment")public String increment() {counterService.increment();return "Count incremented";}@GetMapping("/count")public int getCount() {return counterService.getCount();}
}

4. 测试线程安全问题

可以使用多线程工具(如 Apache JMeter 或者编写一个简单的 Java 多线程程序)来模拟多个线程同时访问 /increment 端点。以下是一个简单的 Java 多线程测试代码:

package com.example.demo;import com.example.demo.service.CounterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@SpringBootApplication
public class DemoApplication implements CommandLineRunner {@Autowiredprivate CounterService counterService;public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}@Overridepublic void run(String... args) throws Exception {ExecutorService executorService = Executors.newFixedThreadPool(50); // 50 个线程并发int threadCount = 1000;for (int i = 0; i < threadCount; i++) {executorService.submit(() -> counterService.increment());}executorService.shutdown();while (!executorService.isTerminated()) {// 等待所有任务完成}System.out.println("Expected count: " + threadCount); // 预期 1000System.out.println("Actual count: " + counterService.getCount()); // 实际值很可能小于 1000}
}

原理分析

count++ 操作由 “读取 count 值 → 对值加 1 → 写回新值” 三个步骤组成,并非原子操作。
当多个线程执行到 Thread.sleep(1) 时,会释放 CPU 时间片,其他线程可能在此时读取到相同的 count 值,导致最终结果小于预期(如 998、990 等),从而体现出单例 Bean(有状态且无同步措施)的线程安全问题。

 

解决方案

在 Spring Boot 中,若单例 Bean 存在状态(如包含可变成员变量),需通过以下方式解决线程安全问题:

1. 同步机制(如 synchronized

通过对方法或代码块加锁,确保同一时间只有一个线程执行关键代码。

import org.springframework.stereotype.Service;@Service
public class CounterService {private int count = 0;// 对方法加锁,保证原子性public synchronized void increment() {count++;}public int getCount() {return count;}
}

原理:synchronized 会在方法或代码块执行时获取锁,其他线程需等待锁释放,避免多个线程同时修改共享变量。

2. 使用原子类(如 AtomicInteger

Java 并发包 java.util.concurrent.atomic 提供的原子类,其方法(如 incrementAndGet)内部通过底层机制(如 CAS)保证操作原子性。

import org.springframework.stereotype.Service;
import java.util.concurrent.atomic.AtomicInteger;@Service
public class CounterService {private AtomicInteger count = new AtomicInteger(0);public void increment() {count.incrementAndGet(); // 原子操作}public int getCount() {return count.get();}
}

 原理:原子类通过硬件级别的原子操作或乐观锁(CAS)确保对变量的修改是线程安全的,避免传统锁的性能开销。

3. ThreadLocal 隔离线程变量

为每个线程提供独立的变量副本,避免线程间共享数据。

import org.springframework.stereotype.Service;@Service
public class CounterService {private ThreadLocal<Integer> count = ThreadLocal.withInitial(() -> 0);public void increment() {count.set(count.get() + 1); // 操作当前线程的副本}public int getCount() {return count.get();}// 建议在使用后清理,防止内存泄漏public void clean() {count.remove();}
}

4. 修改 Bean 作用域为 prototype

将单例(singleton)改为原型(prototype),每次请求都会创建新的 Bean 实例,避免多线程共享状态。

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;@Service
@Scope("prototype") // 每次请求创建新实例
public class CounterService {private int count = 0;public void increment() {count++;}public int getCount() {return count;}
}

原理:原型作用域下,每个线程获取独立的 Bean 实例,线程间无共享状态,从而避免线程安全问题,但会增加对象创建开销。

  实际应用中,可根据场景选择:

  • 简单场景优先用 原子类(性能高)或 同步方法(实现简单)。
  • 若变量需线程内共享但跨线程隔离,用 ThreadLocal
  • 若 Bean 实例创建开销小且需彻底隔离,用 prototype 作用域

http://www.dtcms.com/wzjs/75502.html

相关文章:

  • vue.js网站如果做自适应网络推广一个月的收入
  • 龙岩一中网站软文营销文章范文
  • 做网站分什么有了域名如何建立网站
  • 做一手房产中介用什么网站好网络广告投放平台
  • 网站建设信息宁波seo网络推广公司排名
  • vs2010怎么做网站前台安卓优化软件
  • 哪里有网站开发服务网上推广app
  • 电脑上做免费网站教程视频中国互联网协会
  • 12306网站是阿里做的搜素引擎优化
  • 网站流媒体播放如何做好口碑关键词优化
  • 哪个网站可以做线上翻译赚钱网络服务器的功能
  • 如何的找网站建设公司电脑系统优化软件十大排名
  • 杨浦网站建设 网站外包产品推广介绍
  • 手机网站首页布局设计google权重查询
  • 免费建站网站黄金网站中企动力做网站推广靠谱吗
  • 好搜网站提交入口网上哪里可以免费打广告
  • 网站已经编辑好了 上线准备哪些工作青岛网站快速排名优化
  • 做外贸网站哪家效果好最新新闻实时新闻
  • 网络广告文案深圳seo优化公司
  • 一些网站只能在微信打开怎么做的网站关键词优化怎么弄
  • 没有服务器怎么先做网站军事新闻最新
  • 怎样建设电影网站中关村在线app
  • 网站建设收费流程免费培训机构
  • 太原网站建设世纪优创软件开发公司经营范围
  • ai网站设计百度一下首页网页百度
  • 做网站的价钱网络服务公司
  • 做公司网站的服务费入什么费用河南网站建设哪里好
  • 樟木头镇做网站网络营销推广方案步骤
  • 湛江有帮公司做网站一站式网络营销
  • 企业网站包含内容新发布的新闻