精华内容
下载资源
问答
  • 当方法开启了新的线程,并将方法的局部变量传递给了新的线程(并且仅当新线程对局部变量进行值修改时),这时,就产生了多个线程共享同一个变量,并且对变量进行修改,所以会造成引发并发问题 ...
    • 并发问题的定义:并发的定义,什么是并发问题
    • 当方法开启了新的线程,并将方法的局部变量传递给了新的线程(并且仅当新线程对局部变量进行值修改时),这时,就产生了多个线程共享同一个变量,并且对变量进行修改,所以会造成引发并发问题
    展开全文
  •  因为接口返回json数据,因此可以通过jmeter的后置处理器插件“jp@gc - JSON Path Extractor”解析请求结果,作为一个局部变量,从而为下一个接口所用。    备注:设不设置集合点,传入的token都不一致  2.3.2 ...

    1. 业务场景

    5个用户登录系统,需要将登录接口A返回的token作为接口B的入参。接口B设置集合点,同时请求后台接口。

    2. 脚本

    2.1  目录结构

            

            2.2  多个用户信息获取

                    采用csv文件存储用户信息

                 

            

             2.3  局部变量和全局变量压测

                2.3.1 以局部变量的形式传参

                       因为接口返回json数据,因此可以通过jmeter的后置处理器插件“jp@gc - JSON Path Extractor”解析请求结果,作为一个局部变量,从而为下一个接口所用。

                    


                   备注:设不设置集合点,传入的token都不一致

                   2.3.2 以全局变量的形式传参

                       因为接口返回json数据,因此可以通过jmeter的后置处理器插件“jp@gc - JSON Path Extractor”解析请求结果,并利用后置处理器插件BeanShell PostProcessor将解析结果置为全局变量。



                备注:全局变量方式,如果不设置集合点,传入的token是不同的值,但起不到并发测试的作用;如果设置集合点,传入的token是一致的。










    展开全文
  • 一、线程局部变量 1、如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作时,它们对该成员变量是...3、如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝(即便是同一个对象的方

    一、线程局部变量

    1、如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作时,它们对该成员变量是彼此影响的,也就是说一个线程对成员变量的改变会影响到另一个线程。

    2、在某种情况下,对象的属性不需要被所有线程共享。可以采用 Java api 提供的一个干净的机制-----线程局部变量 <Thread -Local Variable>

    3、如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝(即便是同一个对象中的方法的局部变量,也会对每一个线程有一个拷贝),一个线程对该局部变量的改变不会影响到其他线程

    二、ThreadLocal

    1、ThreadLocal提供的方法

    		public T get() { } //用来获取ThreadLocal在当前线程中保存的变量副本
    		public void set(T value) { } //set()用来设置当前线程中变量的副本
    		public void remove() { } //用来移除当前线程中变量的副本
    		protected T initialValue() { } //是一个protected方法,一般是用来在使用时进行重写的,它是一个延迟加载方法

    2、ThreadLocal的使用场景:数据库连接、Session管理等。

    3、ThreadLocal是如何做到为每一个线程维护变量的副本的呢?----使用map

    对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

    4、查看源码

    public T get() {
            Thread t = Thread.currentThread(); //获取当前线程
            ThreadLocalMap map = getMap(t); //获取一个map,map的类型为ThreadLocalMap。
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this); //获取到<key,value>键值对,注意这里获取键值对传进去的是  this,而不是当前线程t。
                if (e != null) { //如果获取成功,则返回value值
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            return setInitialValue(); //map为空,则调用setInitialValue方法返回value
        }


    GetMap怎么实现的?
    //getMap干了什么?
    	ThreadLocalMap getMap(Thread t) {
            return t.threadLocals;//调用当期线程t,返回当前线程t中的一个成员变量threadLocals
        }


    threadLocals是什么?

     //threadLocals是什么?实际上就是一个ThreadLocalMap,这个类型是ThreadLocal类的一个内部类
        ThreadLocal.ThreadLocalMap threadLocals = null;

    5、原理

    首先,Thread这个类有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,

    ThreadLocal.ThreadLocalMap threadLocals = null;

    这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找

    三、使用实例

    	// 声明一个ThreadLocal<Date>对象,这个对象是在initialValue()方法中隐式实现的
    	private ThreadLocal<Date> startDate = new ThreadLocal<Date>() {
    		protected Date initialValue() {
    			return new Date();
    		};
    	};



    展开全文
  • 如果说互斥同步是多线程间的数据共享,那么线程局部变量就是线程间的数据隔离。ThreadLocal把共享数据的可见范围限制在同一个线程之内,这样无须同步也能实现线程之间数据不争用的问题。当使用ThreadLocal维护变量时...

    今天我们来讨论另外一种线程安全的实现方法。如果说互斥同步是多线程间的数据共享,那么线程局部变量就是线程间的数据隔离。ThreadLocal把共享数据的可见范围限制在同一个线程之内,这样无须同步也能实现线程之间数据不争用的问题。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。线程局部变量实现的原理也比较简单:每个线程的Thread对象中都有一个ThreadLocalMap对象,这个map存储了一组以该线程所对应的哈希码ThreadLocal.threadLocalHashCode为键,以线程局部变量为值的K-V值对,每一个线程对象都包含了一个独一无二的threadLocalHashCode值,使用这个值就可以获取相对应的变量了,这个变量就是上文中提到的线程局部变量的副本。
    我们来分析一下java中最常用到的日期时间格式化工具类SimpleDateFormat。SimpleDateFormat类用来对日期字符串进行解析和格式化输出,但如果使用不小心会导致非常微妙和难以调试的问题,因为 DateFormat 和 SimpleDateFormat 类都不是线程安全的,以下代码:

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

    没有使用任何同步手段来确保线程安全,我们使用一个测试用例来测试一下是否运行正常:

    @Test
      public void test01(){
          ExecutorService service = Executors.newCachedThreadPool(); // 创建一个线程池
          for (int i = 0; i < 10; i++) {
            Runnable runnable = new Runnable() {
              public void run() {
                try {
                  System.out.println(Thread.currentThread().getName()+":"+DateUtil.parse("2017-06-24 06:02:20"));
                  Thread.sleep(30000);
                } catch (Exception e) {
                  System.out.println(e.getMessage());
                }
              }
            };
            service.execute(runnable);// 为线程池添加任务
          }
      }

    运行结果为:
    pool-1-thread-2:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-7:Sat Jun 24 06:02:02 CST 2017
    pool-1-thread-3:Sat Jun 24 06:02:02 CST 2017
    pool-1-thread-6:Tue Jul 31 06:02:20 CST 2018
    pool-1-thread-8:Tue Jul 24 06:02:20 CST 2018
    pool-1-thread-4:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-9:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-5:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-1:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-10:Sat Jun 24 06:02:20 CST 2017
    很明显,线程6和线程8输出的时间是有错误的,这是因为SimpleDateFormat和DateFormat类不是线程安全的。在多线程环境下调用 format() 和 parse() 方法应该使用同步代码来避免问题。以下代码:

    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);
          }
      }
    }

    我们使用一个测试用例来测一下看是否运行正常:

    public class SyncTest {
    
      @Test
      public void test01(){
          ExecutorService service = Executors.newCachedThreadPool(); // 创建一个线程池
          final CountDownLatch cdOrder = new CountDownLatch(1);
          for (int i = 0; i < 10; i++) {
            Runnable runnable = new Runnable() {
              public void run() {
                try {
                  System.out.println(Thread.currentThread().getName()+":"+DateSyncUtil.parse("2017-06-24 06:02:20"));
                  cdOrder.await();
                } catch (Exception e) {
                  e.printStackTrace();
                }
              }
            };
            service.execute(runnable);// 为线程池添加任务
          }
      }
    }

    运行结果:
    pool-1-thread-9:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-3:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-4:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-6:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-1:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-2:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-5:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-10:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-8:Sat Jun 24 06:02:20 CST 2017
    通过结果可以看出以上代码肯定是线程安全的,可以保证数据的正确性。但是在高并发环境下,当一个线程调用该方法时,其他想要调用此方法的线程就要阻塞,多线程并发量大的时候会对性能有一定的影响。如果系统对性能有比较高的要求,那么推荐使用ThreadLocal来隔离数据在一个线程中:

    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);
      }
    }

    调用上面的测试用例测试的结果如下:
    pool-1-thread-4:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-8:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-3:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-1:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-6:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-9:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-2:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-5:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-10:Sat Jun 24 06:02:20 CST 2017
    pool-1-thread-7:Sat Jun 24 06:02:20 CST 2017
    使用ThreadLocal,也是将共享变量变为独享,线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。
    虽然ThreadLocal相比于互斥同步在时间性能上面有一定的优势,但是需要注意它们两者所应用的场景,ThreadLocal用于数据隔离,即当很多线程需要多次使用同一个对象,并且需要该对象具有相同初始化值的时候最适合使用ThreadLocal。而synchronized用于数据同步,即当多个线程需要访问或修改某个对象的时候使用synchronized来阻塞其他线程从而只允许一个线程访问或修改该对象。

    展开全文
  • 终于弄懂为啥局部变量是线程安全的了!!
  • Java并发编程--线程局部变量使用

    千次阅读 2015-05-28 09:12:56
    共享数据是并发程序最核心的问题之一。下面我们看一个Deom感受一下多线程对属性的影响。 代码: UnsafeTask.java package com.tgb.klx.thread; import java.text.SimpleDateFormat; import java.util.Date; import ...
  • 相信很多小伙伴都知道局部变量是线程安全的,那你知道为什么局部变量是线程安全的吗? 前言 多个线程同时访问共享变量时,会导致并发问题。那么,如果将变量放在方法内部,是不是还会存在并发问题呢?如果不存在...
  • Spring采用公共变量并发问题解决

    千次阅读 2017-08-03 19:25:20
    由于系统采用springmvc框架,springmvc核心控制器DispatcherServlet 默认为每个controller生成单一实例来处理所有用户...这样就会出现并发请求时变量内容被篡改的问题。那么出现这种问题如何解决呢? 第一种方式:
  • 我们一遍一遍重复再重复地讲到,多个线程同时...那 Java 方法里面的局部变量是否存在并发问题呢?下面我们就先结合一个例子剖析下这个问题。 比如,下面代码里的 fibonacci() 这个方法,会根据传入的参数 n ,返回 1...
  • 局部变量线程安全问题

    千次阅读 2018-01-10 15:49:22
    局部变量线程安全问题 只看楼主 收藏 回复 mincike 沝 2 求大神给解释下 回复 1楼 2016-02-...
  • 问题场景: 方法n内部多线程调用内部局部变量集合,并发写入数据库,集合线程间隔离(线程调用完毕就需要清空集合),数据不重复写入问题 核心代码片段: class ThreadSync implements Runnable { private ...
  • java线程安全问题之静态变量、实例变量、局部变量

    万次阅读 多人点赞 2012-12-14 15:08:06
    java多线程编程,存在很多线程安全问题,至于什么是线程安全呢,给出一... 此处不赘述了,首先给出静态变量、实例变量、局部变量在多线程环境下的线程安全问题结论,然后用示例验证,请大家擦亮眼睛,有错必究,否则
  • 局部变量线程安全的理解

    千次阅读 2017-10-11 20:24:16
    如何理解局部变量线程安全
  • 局部变量不存在线程安全问题。 静态变量在该类的所有实例之间共享,如果会进行修改的话会有线程安全问题。 全局变量在单例时会有线程安全问题,多例时不存在。...
  • Java线程安全问题之静态成员变量、实例成员变量、局部变量 (原文地址:http://blog.csdn.net/will_awoke/article/details/38044415) java多线程编程,存在很多线程安全问题,至于什么是线程安全呢...
  • 由于系统采用springmvc框架,springmvc核心控制器DispatcherServlet 默认为每个controller生成单一实例来处理所有用户...这样就会出现并发请求时变量内容被篡改的问题。 那么出现这种问题如何解决呢? 第一种方式:...
  • 在Java多线程编程有时候会遇见线程本地局部变量ThreadLocal这个类,下面就来讲讲ThreadLocal的使用及源码分析。 ThreadLocal 是Thread Local Varial(线程局部变量)的意思,每个线程在使用线程局部变量的时候都会...
  • F.52: Prefer capturing by reference in lambdas that ...F.52 在lambda表达式使用引用形式捕捉局部变量,包含向算法传递变量的情况。 译者注:如果你不清楚捕捉(capture)是什么,请参考 https://mp.weixin...
  • ThreadLocal与局部变量

    千次阅读 2017-04-22 12:37:18
    ThreadLocal和局部变量有什么区别,我们先看一段代码,如下:public class ThreadLocalLearn { static ThreadLocal<IntHolder> tl = new ThreadLocal(){ protected IntHolder initialValue() { return new I
  • 一种简单的单例模式,使用静态局部变量。 为什么是静态局部变量可以保证线程安全性? 原因是Magic Static特性。如果变量在初始化时,并发线程同时进入到static声明语句,并发线程会阻塞等待初始化结束。这样可以...
  • 文章目录Pre解决并发问题的方法无锁的方式解决并发问题局部变量不可变对象ThreadLocalCAS原子类有锁的方式解决并发问题synchronized关键字ReentrantLock可重入锁 Pre 解决并发问题的方法 解决并发问题的方法分为两...
  • 成员变量和局部变量 1.程序例子: public class HelloThreadTest { public static void main(String[] args) { HelloThread r = new HelloThread(); Thread t1 = new Thread(r); Thread t2 ...
  • Java多线程编程,存在很多线程安全问题,至于什么是...此处不赘述了,首先给出静态变量、实例变量、局部变量在多线程环境下的线程安全问题结论,然后用示例验证,请大家擦亮眼睛,有错必究,否则误人子弟!静态变量:

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 105,173
精华内容 42,069
关键字:

并发问题中局部变量