• 多线程的参数传递


    创建多线程的回调函数时,传入的参数会被当做一个引用保存起来,即使这个参数没有明显的对应到一个变量上。

    即使后来传入的参数指向了其他对象,但是多线程保存的引用是不会变的。

    比如这个程序:

     1     @Test
     2     public void testMultiThread() throws InterruptedException
     3     {
     4         final List<StringBuilder> strs = new ArrayList<StringBuilder>();
     5 
     6         strs.add(new StringBuilder("1"));
     7         strs.add(new StringBuilder("2"));
     8         strs.add(new StringBuilder("3"));
     9         strs.add(new StringBuilder("4"));
    10 
    11         final List<Callable<String>> tasks = new ArrayList<Callable<String>>();
    12         for (final StringBuilder str : strs)
    13         {
    14             tasks.add(new Callable<String>()
    15             {
    16                 public String call() throws Exception
    17                 {
    18                     System.out.println(str.append("Hello").append("@").append(str.hashCode()));
    19                     return str + "Hello";
    20                 }
    21             });
    22         }
    23 
    24         for (int i = 0; i < strs.size(); i++)
    25         {
    26             strs.get(i).append("new");
    27         }
    28 
    29         for (StringBuilder str : strs)
    30         {
    31             System.out.println(str.hashCode());
    32         }
    33 
    34         final ExecutorService executorService = Executors.newFixedThreadPool(5);
    35         executorService.invokeAll(tasks);

    不出意外,因为执行多线程之前,引用指向并未发生变化,所以在多线程外做的修改,会影响到后来的调用。

    4895754
    7477605
    14765756
    33038931
    2newHello@7477605
    1newHello@4895754
    3newHello@14765756
    4newHello@33038931
    

    如果将参数从StringBuilder改为String,结果将发生变化,因为String是不能修改的,执行附加的时候实际上是生成了一个新的对象。

    但是对于已经创建好的多线程任务来说,他们保存的依然是以前的引用。

        @Test
        public void testMultiThread2() throws InterruptedException
        {
            final List<String> strs = new ArrayList<String>();
    
            strs.add("1");
            strs.add("2");
            strs.add("3");
            strs.add("4");
    
            final List<Callable<String>> tasks = new ArrayList<Callable<String>>();
            for (final String str : strs)
            {
                tasks.add(new Callable<String>()
                {
                    public String call() throws Exception
                    {
                        System.out.println(str + "Hello" + "@" + str.hashCode());
                        return str + "Hello";
                    }
                });
            }
    
            for (int i = 0; i < strs.size(); i++)
            {
                strs.set(i, "hello");
            }
    
            for (String str : strs)
            {
                System.out.println(str + "@" + str.hashCode());
            }
    
            final ExecutorService executorService = Executors.newFixedThreadPool(5);
            executorService.invokeAll(tasks);
    
        }
    

      

    多线程内的参数不受外部变化影响:

    hello@99162322
    hello@99162322
    hello@99162322
    hello@99162322
    1Hello@49
    3Hello@51
    4Hello@52
    2Hello@50

    这个例子中,即使在创建了多线程任务之后将strs数组的内容全部清空,也不会对结果造成影响,因为多线程保存了原始的引用。

    对于原始类型,则多线程任务保存了他们的值,也不受外部变化的影响。

  • 相关阅读:
    牛客练习赛44 A 小y的序列 (模拟,细节)
    牛客假日团队赛10 L 乘积最大 (dp,大数)
    三分查找
    几何基础知识点
    POJ 2318 TOYS
    UVA 11916 Emoogle Grid(大步小步算法(解模方程对数) 快速幂 模的逆)
    UVA 11426 GCD
    Aladdin and the Flying Carpet(算术基本定理)
    算术基本定理
    数论总结帖
  • 原文地址:https://www.cnblogs.com/humc/p/5104220.html
Copyright © 2020-2023  润新知