b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

如何在Spring下处理单例模式与线程安全之间的矛盾

电脑杂谈  发布时间:2020-07-09 23:24:21  来源:网络整理

多线程调用单例类中的方法会不会造成线程安全问题?_c 线程安全的单例模式_下面哪个方法可以在任何时候被任何线程调用( )

使用Spring框架时,有多少人不了解或忽略多线程问题?

由于在编写程序或进行单元测试时,很难有机会遇到多线程问题,因为没有容易模拟多线程测试的环境. 然后,当多个线程调用同一个bean时,将出现线程安全问题. 如果Spring中的bean创建模式不是单例,则不会出现这种问题.

但是,如果您不考虑潜在的漏洞,它将成为程序的隐形杀手,在您不知道的时候爆发. 此外,在交付使用该程序时,在生产环境中触发通常很麻烦.

我们知道,在正常情况下,在多线程环境中只能共享无状态Bean. 在Spring中,大多数bean都可以声明为单例作用域. 这是因为Spring使用ThreadLocal来处理某些bean(例如RequestContextHolder,TransactionSynchronizationManager,LocaleContextHolder等)中的非线程安全状态,从而使它们也成为线程安全状态,因为有状态bean可以在多个线程之间共享.

常规Web应用程序分为三层: 表示层,服务层和持久层. 相应的逻辑写在不同的层中,下层通过与上层的接口调用open函数. 通常,从接收请求到返回响应的所有程序调用都属于同一线程

ThreadLocal是解决线程安全问题的好主意. 通过为每个线程提供变量的独立副本,它解决了变量并发访问的冲突问题. 在许多情况下,与直接使用同步同步机制解决线程安全问题相比,ThreadLocal更简单,更方便,并且所产生的程序具有更高的并发性.

下面哪个方法可以在任何时候被任何线程调用( )_多线程调用单例类中的方法会不会造成线程安全问题?_c 线程安全的单例模式

如果有多个线程在与您的代码相同的进程中运行,并且这些线程可能同时运行此代码. 如果每次运行的结果与单线程运行的结果相同,并且其他变量的值也与预期相同,则是线程安全的. 换句话说: 类或程序提供的接口是线程的原子操作,或者在多个线程之间切换不会导致接口的执行结果模棱两可,这意味着我们无需考虑同步问题. 线程安全问题是由全局变量和静态变量引起的.

如果每个线程只对全局变量和静态变量具有读操作,而对写变量则没有写操作,则通常来说,此全局变量是线程安全的;如果多个线程同时执行写操作,通常需要考虑线程同步,否则可能会影响线程安全.

1)常量始终是线程安全的,因为只有读操作.

2)每次调用一个方法都创建一个新实例是线程安全的,因为它不会访问共享资源.

3)局部变量是线程安全的. 因为每个方法都执行,所以局部变量是在单独的空间中创建的,因此它不是共享资源. 局部变量包括方法的参数变量和方法内的变量.

有状态是数据存储功能. 有状态对象(有状态Bean)是具有实例变量的对象,这些实例变量可以存储数据并且不是线程安全的. 在不同的方法调用之间不会保留任何状态.

c 线程安全的单例模式_下面哪个方法可以在任何时候被任何线程调用( )_多线程调用单例类中的方法会不会造成线程安全问题?

无状态是无法保存数据的操作. 无状态对象(Stateless Bean)是没有实例变量的对象. 它们不能存储数据,是不变的类,并且是线程安全的.

有状态对象:

无状态bean适用于不变模式,该技术是单例模式,可以共享实例并提高性能. 有状态Bean在多线程环境中并不安全,因此Prototype是合适的. 原型: 每次对bean的请求创建一个新的bean实例.

Struts2的默认实现是原型模式. 也就是说,每个请求都会生成一个新的Action实例,因此不存程安全问题. 应该注意的是,如果动作的生命周期是由Spring管理的,则该作用域应配置为原型作用域

SimpleDateFormat(以下称为sdf)类具有Calendar对象引用,该引用用于存储与此sdf相关的日期信息,例如sdf.parse(dateStr),sdf.format(date)和喜欢. 与日期相关的字符串,日期等由朋友的Calendar引用存储. 这会引起问题. 如果您的sdf是静态的,则该sdf将在多个线程之间共享,并且此Calendar引用也将被共享. 并且,观察sdf.parse()方法,您会发现以下调用:

 Date parse() {
   calendar.clear(); // 清理calendar
   ... // 执行一些操作, 设置 calendar 的日期什么的
   calendar.getTime(); // 获取calendar的时间
 }

c 线程安全的单例模式_下面哪个方法可以在任何时候被任何线程调用( )_多线程调用单例类中的方法会不会造成线程安全问题?

这里的问题是,如果线程A调用sdf.parse()且calendar.clear()尚未执行calendar.getTime(),则线程B调用sdf.parse(),此时,线程B也将执行sdf.clear()方法,它导致线程A的日历数据被清除(实际上,A和B也同时被清除). 或者当A执行calendar.clear()挂起时,此时B开始调用sdf.parse()并成功结束,因此存储在A的日历中的日期成为B以后设置的日历日期

此问题的背后是一个更重要的问题-无状态: 无状态方法的好处之一是可以在各种环境中安全地调用它. 衡量一个方法是否是有状态的取决于它是否改变了其他东西,例如全局变量,例如实例字段. 格式化方法会在操作过程中更改SimpleDateFormat的Calendar字段,因此它是有状态的.

这也提醒我们在开发和设计系统时要注意以下三点:

注意: 创建一个需要SimpleDateFormat的新实例. 每当将线程安全问题的对象从共享更改为部分私有时,都可以避免多线程问题,但这也会增加创建对象的负担. 在正常情况下,性能影响率不是很明显.

public class DateSyncUtil {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      
    public static String formatDate(Date date)throws ParseException{
        synchronized(sdf){
            return sdf.format(date);
        }  
    }
    
    public static Date parse(String strDate) throws ParseException{
        synchronized(sdf){
            return sdf.parse(strDate);
        }
    } 
}

注意: 当有多个线程时,一个线程调用此方法时,其他要调用此方法的线程将阻塞,并且多线程并发性将对性能产生一定影响.

下面哪个方法可以在任何时候被任何线程调用( )_c 线程安全的单例模式_多线程调用单例类中的方法会不会造成线程安全问题?

public class ConcurrentDateUtil {
    private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };
    public static Date parse(String dateStr) throws ParseException {
        return threadLocal.get().parse(dateStr);
    }
    public static String format(Date date) {
        return threadLocal.get().format(date);
    }
}

ThreadLocal<DateFormat>(); 
 
    public static DateFormat getDateFormat()   
    {  
        DateFormat df = threadLocal.get();  
        if(df==null){  
            df = new SimpleDateFormat(date_format);  
            threadLocal.set(df);  
        }  
        return df;  
    }  
    public static String formatDate(Date date) throws ParseException {
        return getDateFormat().format(date);
    }
    public static Date parse(String strDate) throws ParseException {
        return getDateFormat().parse(strDate);
    }   
}

注意: 使用ThreadLocal还将共享变量更改为互斥. 与方法独占相比,线程独占绝对可以减少在并发环境中创建对象的开销. 如果对性能的要求比较高,通常建议使用此方法.

一个简单的压力测试,方法一是最慢的,方法三是最快的多线程调用单例类中的方法会不会造成线程安全问题?,但是即使最慢的方法一也不错,可以满足一般系统方法一和方法二,因此在这一点上非常好很难成为系统的瓶颈. 从简单的角度来看,建议使用方法一或方法二. 如果需要在必要时略微提高性能,可以考虑使用方法三,并使用ThreadLocal作为缓存.

Joda-Time库非常适合用于时间处理多线程调用单例类中的方法会不会造成线程安全问题?,因此建议使用.

回到文章开头的问题: “有多少人使用Spring框架,经常不知道或忽略多线程问题?”

实际上,任何人都可以编写代码,为什么架构师编写的代码的效果与您的不同?这应该是一个很小的问题,您尚未考虑,而架构师已经考虑了.

建筑师在解决各种问题方面拥有更广泛的知识,更具体的情况和更多经验. 只要您发展出建筑师的思想和习惯,您还会远离建筑师吗?


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-274659-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...