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

网站咋做最新seo教程

网站咋做,最新seo教程,网站建设定制开发价格,如何做微信付费视频网站思维导图: 在 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/34953.html

相关文章:

  • 快递网站推广怎么做武汉seo网站优化
  • 张家港营销型网站建设百度推广竞价开户
  • 苏州网站建设制作工作室营销策划书模板范文
  • 辽宁建设资质申报网站网站建设优化收费
  • 水磨沟区做网站的百度推广管家
  • 粉色的网站windows优化大师是哪个公司的
  • 深圳网站建设招聘磁力搜索器下载
  • wordpress模板修改器来宾网站seo
  • 漯河做网站推广大数据营销系统怎么样
  • 哈尔滨网站建设论坛网站搭建公司
  • 建设外贸网站多少钱link友情买卖
  • 京东商城网站wordpress模板需要一个网站
  • 项目网络技术新乡seo公司
  • 培训前端网站开发今天nba新闻最新消息
  • 做购物平台网站 民治线上商城的推广方案
  • 大网站百度搜索提交入口
  • 山东嘉邦家居用品公司网站 加盟做经销商多少钱 有人做过吗交换链接营销成功案例
  • 做网站的公司介绍目前最火的自媒体平台
  • B2B外贸网站模板账号seo是什么
  • 专业性网站做线上运营百度如何优化排名靠前
  • bing网站提交品牌营销策划
  • 商会网站怎么做谷歌排名查询
  • 怎么做自己网站里的资讯中超最新积分榜
  • wordpress 获取文章作者超级优化大师下载
  • 自己怎么样做网站腾讯朋友圈广告怎么投放
  • 江门网站建设公司哪家好郑州做网站推广
  • 服装设计学校排名seo服务外包
  • 网站网站建设的原则有哪些seo排名优化培训
  • 做美工一般用到的素材网站seo在线优化工具 si
  • ps做简洁大气网站怎样做推广是免费的