GVKun编程网logo

spring控制器-线程安全性和存储资源(spring controller 线程安全)

5

以上就是给各位分享spring控制器-线程安全性和存储资源,其中也会对springcontroller线程安全进行解释,同时本文还将给你拓展java–SpringData(JPA)存储库是否是线程安全

以上就是给各位分享spring控制器-线程安全性和存储资源,其中也会对spring controller 线程安全进行解释,同时本文还将给你拓展java – Spring Data(JPA)存储库是否是线程安全的? (又名SimpleJpaRepository线程安全)、java – Spring控制器线程安全吗?、JAVA 并发编程 - Spring 并发访问的线程安全性问题、printf的线程安全性以及cout的线程不安全性验证,以及意外收获等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

spring控制器-线程安全性和存储资源(spring controller 线程安全)

spring控制器-线程安全性和存储资源(spring controller 线程安全)

我对spring mvc和线程安全性有疑问。

我们正在开发将存储在tomcat上的Web应用程序。如果我理解正确,Tomcat将为每个请求创建线程,并且它具有一些线程池。现在,调度程序servlet在请求之间共享,并且可能是线程安全的。

但是当我这样创建控制器时:

@Controller@RequestMapping("/manage")public class QuestionManagementController {

他具有Singleton作用域,因此来自每个用户的每个请求都使用相同的控制器。

我想知道通常如何解决此问题:

1:控制器是通过Session作用域创建的吗?(但我认为,如果一个用户快速执行某些操作可能会导致控制器出现争用情况,那么也会出现问题)。

2:控制器的作用域为 request

3:创建在类级别不共享任何变量或使其处于只读模式的无状态控制器

也许有一些更好的“最佳实践”可以解决此类问题。

我问这个问题,因为现在我们将它们作为Singleton作用域,并且存在一个问题,在大多数方法中,我们正在数据库中查询用户,并且由于作用域,我们无法将此信息存储在类级别的变量中。我们可以尝试使用一些线程安全的集合,但是稍后可能还有其他资源需要同步访问。

答案1

小编典典

一个很多参数可以被添加到控制器方法,如请求,会话,校长等,以避免您的问题。

通常有一个三层架构:

  • @Controller (他们代表服务)
  • @Service (他们使用DAO或存储库进行工作)
  • @Repository (或DAO,它们可以访问数据库)

因此,根据您在数据库中查询的内容,我建议您使用Spring注入的服务,如果命中数据库的代价高昂,并且每次您需要数据库中的内容时,都会通过缓存注入该服务(即,控制器中没有存储任何内容)班级)

举一个简短的例子,假设我们落后于spring-
security,并且一切都需要一个完全登录的用户。我们有一个userData表,其中的键是用户登录名,我们有一个URL
/data以获取显示我的用户数据的页面:

@Controller@RequestMapping("/data")public class UserDataController{    @Autowired    private UserService userService;    @RequestMapping(value = "", method = RequestMethod.GET)    public ModelAndView data(final Principal principal) {        Assert.notNull(principal); // throw if assertion fails        Assert.hasText(principal.getName());        final UserData userData = this.userService.findByUserName(principal.getName());        Assert.notNull(userData, "userData not found");        return new ModelAndView("userData", "userData", userData);    }}@Service("userService")public class userService {    private static final String USERDATA_CACHE = "com.acme.foo.UserData";    @Autowired    private UserDataRepository userDataRepository;    @Cacheable(USERDATA_CACHE)    public UserData findByUserName(final String userName) {        return this.userDataRepository.findByUserName(userName);    }}@Repositorypublic class UserDataRepository{    // or use spring-data-jpa    public UserData findByUserName(final String userName) {        // query table userData and create an UserData from results.    }}

在这里,我使用principal和spring确保这是当前用户之一。

参考:

  • @Cachable
  • 另请参见在Spring Framework 3 MVC中初始化Singleton

请注意,此答案是否完全解决了您的问题

java – Spring Data(JPA)存储库是否是线程安全的? (又名SimpleJpaRepository线程安全)

java – Spring Data(JPA)存储库是否是线程安全的? (又名SimpleJpaRepository线程安全)

我使用Spring Data (JPA) repository来处理CRUD样板.

我这样定义我的存储库接口:

import org.springframework.data.repository.CrudRepository;

public interface FooRepository extends CrudRepository

Spring然后自动神奇地生成我所述接口的实现.我们得到的是代理,但我相信最终我们会得到一个org.springframework.data.jpa.repository.support.SimpleJpaRepository.

如果底层目标类是线程安全的,则JdkDynamicAopProxy是线程安全的.因此问题是:SimpleJpaRepository线程安全吗?

最佳答案
一般来说,是的.它假定一个托管的EntityManager,我们将从Spring的工厂类中获取(如果您使用Spring作为容器)或者作为CDI托管bean(通过@Producer方法声明).

java – Spring控制器线程安全吗?

java – Spring控制器线程安全吗?

我正在 Spring Controller中编写一个私有实用程序方法.

我需要使用StringBuffer或StringBuilder.前者是线程安全的,后者不是,但后者要快得多.

基本上,它看起来像这样:

private String buildTextTodisplay() {
    StringBuffer sb = new StringBuffer();
    sb.append( ... );
    return sb.toString();
}

显然,我不希望两个会话同时调用它并返回垃圾.

解决方法

由于sb是局部变量,因此它不需要是线程安全的. (每个线程都有自己对唯一StringBuilder的引用,对吧?)

JAVA 并发编程 - Spring 并发访问的线程安全性问题

JAVA 并发编程 - Spring 并发访问的线程安全性问题

OSC 请你来轰趴啦!1028 苏州源创会,一起寻宝 AI 时代

   首先对于 Spring 的 IOC 来说,对象是由 Spring 来帮我们管理,也就是在 Spring 启动的时候,在 Spring 容器中,由 Spring 给我们创建的,Spring 会帮我们维护,一般都是单例的,也就是一个对象。


spring 生成对象默认是单例的。通过 scope 属性可以更改为多例。


第一部分:验证 Spring 生成对象默认是单例的。


下面我们来一个网上的例子验证一下:

<bean id="singleton" class="java.util.Date" scope="singleton"></bean>  
<bean id="prototype" class="java.util.Date" scope="prototype"></bean>
package test;   
import java.util.Date;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
import com.opensymphony.xwork2.ActionContext;  
public class TestScope {  
    public static void main(String[] args) {  
       ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext-web.xml");  
       Date s1=(Date)context.getBean("singleton");  
       Date p1=(Date)context.getBean("prototype");  
       Date s2=(Date)context.getBean("singleton");  
       Date p2=(Date)context.getBean("prototype");  
   System.out.println("单例:"+(s1==s2));  
  System.out.println("非单例:"+(p1==p2));  
    } 
}



输出结果:

结果

单例:true

非单例:false


注:复合数据类型的 “== ” 对比的是内存中存放的地址,所以此处我们采用 “==” 去对比

因为 object 中的 equals 初始行为是比较内存中的地址,但在一些类库中被覆盖掉了如(String,Integer,Date 等)


第二部分:SpringMVC 和 Struts2 中是并发访问否会存在线程安全问题。


对于使用过 SpringMVC 和 Struts2 的人来说,大家都知道 SpringMVC 是基于方法的拦截,而 Struts2 是基于类的拦截。


对于 Struts2 来说,因为每次处理一个请求,struts 就会实例化一个对象;这样就不会有线程安全的问题了 ;

而 Spring 的 controller 默认是 Singleton 的,这意味着每一个 request 过来,系统都会用原有的 instance 去处理,这样导致两个结果:

一是我们不用每次创建 Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个 Controller 的 instance,当多个线程调用它的时候,它里面的 instance 变量就不是线程安全的了,会发生窜数据的问题。


当然大多数情况下,我们根本不需要考虑线程安全的问题,比如 dao,service 等,除非在 bean 中声明了实例变量。因此,我们在使用 spring mvc 的 contrller 时,应避免在 controller 中定义实例变量。 

如:

public class Controller extends AbstractCommandController {    
    protected Company company;  
    protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response,Object command,BindException errors) throws Exception {  
        company = ................;           
     }             
 }

 解决方案:

有几种解决方法:
1、在 Controller 中使用 ThreadLocal 变量
2、在 spring 配置文件 Controller 中声明 scope="prototype",每次都创建新的 controller
所在在使用 spring 开发 web 时要注意,默认 Controller、Dao、Service 都是单例的。


例如:

@Controller  
@RequestMapping("/fui")  
public class FuiController extends SpringController {  
//这么定义的话就是单例  
  
@Controller  
@Scope("prototype")  
@RequestMapping("/fui")  
public class FuiController extends SpringController {  
//每次都创建

第三部分:springMVC 与 struts2 的区别。

下面是从网络上摘抄的一段对比,大家可以看看点击打开链接

1. 机制:spring mvc 的入口是 servlet,而 struts2 是 filter,这样就导致了二者的机制不同。 

2. 性能:spring 会稍微比 struts 快。spring mvc 是基于方法的设计,而 sturts 是基于类,每次发一次请求都会实例一个 action,每个 action 都会被注入属性,而 spring 基于方法,粒度更细,但要小心把握像在 servlet 控制数据一样。spring3 mvc 是方法级别的拦截,拦截到方法后根据参数上的注解,把 request 数据注入进去,在 spring3 mvc 中,一个方法对应一个 request 上下文。而 struts2 框架是类级别的拦截,每次来了请求就创建一个 Action,然后调用 setter getter 方法把 request 中的数据注入;struts2 实际上是通过 setter getter 方法与 request 打交道的;struts2 中,一个 Action 对象对应一个 request 上下文。 

3. 参数传递:struts 是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。

4. 设计思想上:struts 更加符合 oop 的编程思想, spring 就比较谨慎,在 servlet 上扩展。 

5. intercepter 的实现机制:struts 有以自己的 interceptor 机制,spring mvc 用的是独立的 AOP 方式。这样导致 struts 的配置文件量还是比 spring mvc 大,虽然 struts 的配置能继承,所以我觉得论使用上来讲,spring mvc 使用更加简洁,开发效率 Spring MVC 确实比 struts2 高。spring mvc 是方法级别的拦截,一个方法对应一个 request 上下文,而方法同时又跟一个 url 对应,所以说从架构本身上 spring3 mvc 就容易实现 restful url。struts2 是类级别的拦截,一个类对应一个 request 上下文;实现 restful url 要费劲,因为 struts2 action 的一个方法可以对应一个 url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc 的方法之间基本上独立的,独享 request response 数据,请求数据通过参数获取,处理结果通过 ModelMap 交回给框架方法之间不共享变量,而 struts2 搞的就比较乱,虽然方法之间也是独立的,但其所有 Action 变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。 

6. 另外,spring3 mvc 的验证也是一个亮点,支持 JSR303,处理 ajax 的请求更是方便,只需一个注解 @ResponseBody ,然后直接返回响应文本即可。

总结:

这样也说明了 SpringMVC 还有 Servlet 都是方法的线程安全,所以在类方法声明的私有或者公有变量不是线程安全的,而 struts2 的确实是线程安全的。


第四部分:那么对于 Struts2+Spring 来管理注入的时候呢?

Struts2 它是多实例的,对于每个请求都会生成 1 个实例,spring 默认是单实例的(下面针对 Struts 与 Spring 集成的两种方式分别来介绍 struts2 和 spring 的两种整合方式)

一:对于无 Spring 插件(Struts2-spring-plugin-XXX.jar)的整合方式,需要在 spring 的 action Bean 中加业务逻辑控制器类配 scope="prototype"。

<bean id="user" class="modle.User" scope="prototype"></bean>  

二:对于有 Spring 插件(Struts2-spring-plugin-XXX.jar)的整合方式:反编译 StrutsSpringObjectFactory 以及相关的代码才发现,如果在 struts action 的配置文件中 <action name=".."/> 中 class 写的如果是完整的包名和类名的话就是 struts 创建 action 对象,也就是多实例的;


总结:如果是 spring 配置文件中的 bean 的名字的话就是 spring 创建,那么单实例还是多实例就由 spring 的 action Bean 中的业务逻辑控制器类是否配置为 scope=”prototype”,有就是多实例的,没有就是单实例的,顺序是先从 spring 中找,找不到再从 struts 配置文件中找。





printf的线程安全性以及cout的线程不安全性验证,以及意外收获

printf的线程安全性以及cout的线程不安全性验证,以及意外收获

码给你,自测。

#include <iostream>
#include <thread>
#include <atomic>
#include <ctime>
#include <mutex>

using namespace std;
std::atomic_int a;
//int a;
std::mutex _mutex;

void add_() {
	for (int i = 0; i < 10000; i++) {
		_mutex.lock();
		a++;
		_mutex.unlock();
		//printf("%d\n", a);	//这个有点快啊	3.831
		std::cout << a << std::endl;	
		//cout << a << endl;	//有没有std速度差不多
	}
}

int main()
{
    clock_t startTime, endTime;
	
	//add_();	//一条线程空跑:12.753

	//atomic:11.744		下午再测 5.757s
	//上锁:11.954	下午再测 5.891s
	startTime = clock();//计时开始
	std::thread t1(add_);
	std::thread t2(add_);

	t1.join();
	t2.join();
    endTime = clock();//计时结束
    std::cout << "The run time is: " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << std::endl;
    system("pause");
    return 0;
}






本文同步分享在 博客“看,未来”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

我们今天的关于spring控制器-线程安全性和存储资源spring controller 线程安全的分享就到这里,谢谢您的阅读,如果想了解更多关于java – Spring Data(JPA)存储库是否是线程安全的? (又名SimpleJpaRepository线程安全)、java – Spring控制器线程安全吗?、JAVA 并发编程 - Spring 并发访问的线程安全性问题、printf的线程安全性以及cout的线程不安全性验证,以及意外收获的相关信息,可以在本站进行搜索。

本文标签: