多线程的参数传递

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

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

 

比如这个程序:

复制代码
 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);
复制代码

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

1
2
3
4
5
6
7
8
4895754
7477605
14765756
33038931
2newHello@7477605
1newHello@4895754
3newHello@14765756
4newHello@33038931

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@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数组的内容全部清空,也不会对结果造成影响,因为多线程保存了原始的引用。

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

 

posted on   HuMingChuan  阅读(1752)  评论(0编辑  收藏  举报

编辑推荐:
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
阅读排行:
· 不到万不得已,千万不要去外包
· C# WebAPI 插件热插拔(持续更新中)
· 会议真的有必要吗?我们产品开发9年了,但从来没开过会
· 【译】我们最喜欢的2024年的 Visual Studio 新功能
· 如何打造一个高并发系统?
< 2025年1月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

导航

统计

点击右上角即可分享
微信分享提示