多线程的参数传递
创建多线程的回调函数时,传入的参数会被当做一个引用保存起来,即使这个参数没有明显的对应到一个变量上。
即使后来传入的参数指向了其他对象,但是多线程保存的引用是不会变的。
比如这个程序:
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数组的内容全部清空,也不会对结果造成影响,因为多线程保存了原始的引用。
对于原始类型,则多线程任务保存了他们的值,也不受外部变化的影响。
分类:
Java多线程
posted on 2016-01-06 00:42 HuMingChuan 阅读(1752) 评论(0) 编辑 收藏 举报
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 不到万不得已,千万不要去外包
· C# WebAPI 插件热插拔(持续更新中)
· 会议真的有必要吗?我们产品开发9年了,但从来没开过会
· 【译】我们最喜欢的2024年的 Visual Studio 新功能
· 如何打造一个高并发系统?