`
mondayw
  • 浏览: 146159 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

[译文]一些Java并发技巧

    博客分类:
  • Java
阅读更多

原文:Some Java Concurrency Tips

作者:Carol McDonald

出处:http://weblogs.java.net/blog/caroljmcdonald/archive/2009/09/17/some-java-concurrency-tips

 

这是来自Joshua BlochBrian Goetz和其他人的一个关于一些并发技巧的汇总。

 

首先选择不可变的对象/数据

 

不可变对象(immutable object)在构建之后就不会改变了,不可变对象更简单、安全,不需要锁,并且是线程安全的。为了使得不可变对象无需提供setter/mutator方法,把域修饰成private final的,并可防止其子类别化。如果不可选择不变性,那么限制可变的状态,越少的可变状态意味着越少的协调配合。在任何实际可行的情况下把域声明成final的,final域比可变域要简单得多。

在线程共享可变数据的时候,每个读线程或者写线程都必须要协调对数据的访问,未能同步共享的可变数据可能会导致原子性的失败、竞争条件、不一致的状态,以及其他形式的非确定性。这些不确定的问题都是最难以调试的。

使并发交互只在明确定义的地方发生,减少共享数据,考虑复制而不是共享。

 

Web应用的线程风险

 

一个Servletgetpostservice方法能够同时被多个客户端调用,多线程Servlet实例和静态变量是共享的,因此如果是可变的话,那么访问必须加以协调。Servlet是典型的生命期长且被线程高频度加载的对象,如果过分同步的话性能会受影响,或者尽量共享不可变(final)数据,或者尝试完全不共享,请求参数和局部变量会更安全。

 

保持锁定的时间尽可能的短

 

在同步区内完成尽可能少的工作,把不需要加锁的代码放到同步代码块之外,特别是如果这些代码非常耗时的话!

 



  

Lock接口比使用同步代码块提供了更详尽的锁定操作,其有一个好处是如果锁是不可用的话,则不会导致阻塞。你应该只有在需要的时候才获取锁来读取或者写入共享的数据,并在一个finally子句内部解锁,以确保锁被释放。下面是一个使用ReentrantReadWriteLock的例子:

 



  

一种减少保持锁定的时间的做法是锁分拆或者锁分离,该方法是为各个状态变量使用不同的锁而不是使用单个锁,这减小了锁的粒度,提供了更好的可伸缩性,但必须要按照规则顺序来取用锁,否则会有死锁的危险。

 

首先选择executortask而不是thread

 

使用Java并发工具Executor框架(Java Concurrency Utilities Executor Framework)而不是直接使用thread来工作。Executor服务把任务的提交从执行策略中分离出来,从可运行任务的角度来考虑,由executor服务来执行这些任务。

 



  

executor可以被直接创建或者是通过使用Executors类的工厂方法来创建:

 



  

 



  

现在给出一个使用ExecutorExecutorsExecutorService类的例子:

 



  

这个例子是一个web service类,该类使用一个固定的线程池来处理多路同时传入的连接(connection),固定线程池使用返回一个ExecutorService对象的Executors类的newFixedThreadPool方法来初始化,收到的连接通过调用ExecutorService类型的pool对象的execute方法来处理,给该方法传入一个Runnable对象,Runnable对象的run方法处理连接,当run方法执行完成时,线程会被自动返还给线程池。如果有连接进来但所有的线程都已正被使用的话,那么主循环将会阻塞直到有一个线程被释放。

 

首先选择并发实用工具而不是waitnotify操作

 

每次只要你打算使用waitnotify方法时,查看一下java.util.concurrent中是否有你所需要的类,并发集合总是会提供诸如ListQueueMap一类的标准集合接口的高性能并发实现。

 



  

BlockingQueue是带有扩展的阻塞方法的并发对象,这些方法会一直等待(或者阻塞),直到检索的元素变为可用的,或者是存储空间变为可用的时才继续执行。

 



  

生产者消费者模式

 

阻塞队列对生产者消费者模式(Producer Consumer Pattern)来说很有用,在该模式中,生产者线程把工作项目加入队列而消费者线程则把工作项目从队列中取出并进行处理。以下是一个被多个线程使用的记录器的消费者模式(Consumer Pattern)例子:

 



  

下面是使用logger的生产者(Producer)的例子,一个新的ArrayBlockingQueue被实例化以传递给logger的构造方法,在run方法中,信息被放入队列中以进行记录,如果队列满了的话,则放入操作会被阻塞直到logger已把队列中的消息取走才继续。

 



  

同步器

 

同步器是一些用来帮助线程间的协调访问的对象,最常用的同步器是倒计数锁存器(CountDownLatch)和信号量(Semaphore),同步器的使用可以消除大多数wait或者notify方法的使用。

 



  

下面是一个使用信号量来控制资源池访问的例子,多个线程可以请求使用一个资源,并在完成使用后把它交还。

在构造方法中,我们创建了一个新的信号量,信号量的大小与我们正在创建的资源池的大小相同。

getResource()方法中,信号量的aquire方法被调用,尝试取得使用资源的许可,如果有资源可用的话,则该方法会有返回,然后会从池中返回一个资源。如果所有的资源都正在使用当中的话,则aquire方法的调用会阻塞,直到另一个线程调用该信号量的release方法时才继续执行。当某个线程完成资源的使用时,该资源会被返还给池,然后release方法会被调用。aquirerelease方法都可以看作是原子操作。

 



  

多线程的延迟初始化需要一些技巧

 

当多个线程共享一个延迟初始化的域时,对该域的访问必须是同步的,否则可能会导致一些非确定性的错误出现。

 



  

首先选择正常的初始化

 

不要使用延迟初始化,除非对象或者域的初始化代价昂贵且不经常使用。通常情况下,正常的初始化是最好的;) 下面是一个线程安全的单例(singleton)预先初始化的例子,私有的final实例域和私有的构造方法使得该单例是不可变的。

 



  

如果基于静态域的性能问题而需要使用延迟加载的话,则使用按需初始化持有者模式(initialize-on-demand holder pattern),该模式利用了类直到被使用时才会初始化这一担保

 



  

参考资料和更多信息:

 

Effective Java,第二版,Joshua Bloch

Java Concurrency in PracticeBrian Goetz

Robust and Scalable Concurrent Programming: Lessons from the Trenches

Concurrency: Past and Present

  • 大小: 49.9 KB
  • 大小: 63.1 KB
  • 大小: 43.4 KB
  • 大小: 49.2 KB
  • 大小: 44.4 KB
  • 大小: 34.3 KB
  • 大小: 32.8 KB
  • 大小: 46.6 KB
  • 大小: 29.4 KB
  • 大小: 52.9 KB
  • 大小: 45.9 KB
  • 大小: 48.3 KB
  • 大小: 44 KB
  • 大小: 39.3 KB
  • 大小: 47 KB
分享到:
评论

相关推荐

    毕业论文专业译文-Java堆

    你可能已经遇到过由对象泄露或堆大小不足无法存储所有数据导致的Java堆`OutOfMemoryError`,并且可能学习了一些调试这些情况的技巧。然而,随着你的Java应用处理的数据量和并发负载增加,你可能会遇到即使Java堆未满...

    ways-to-java-study.rar_site:www.pudn.com

    "ways-to-java-study.rar"这个压缩包文件显然包含了帮助学习Java的资源,特别是"1000 Java Tips翻译",这可能是一个包含了一千个Java编程技巧和解决常见问题的中文译文集。这些提示和解决方案对于初学者以及有经验的...

    J2ME游戏优化秘密_译文.txt

    通过这个例子,我们可以了解到J2ME游戏开发的一些基本技巧,比如如何处理用户输入、如何更新界面状态等。 综上所述,J2ME游戏优化是一个复杂但至关重要的过程。它不仅涉及到代码层面的细节调整,还需要对游戏设计有...

    Python常用类库.docx

    - **并发性能比较**: 分析了Python几种并发实现方案的性能差异。 - **Web应用平台对比**: 对比了不同Python Web应用框架,如web.py、web2py等。 - **wxPython下的图像处理**: 探讨了在wxPython环境下进行图像处理的...

    55links友情链接网址跟踪器

    55links友情链接网址跟踪器,放在桌面,每次直接打开就可以访问55links友情链接交易平台,方便快捷。

    [AB PLC例程源码][MMS_046180]CompactFlash Data Storage.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    moore_01_0909.pdf

    moore_01_0909

    FIBR English learning

    FIBR English learning

    [AB PLC例程源码][MMS_042350]How to send-receive SMS text messages using Westermo modem.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    OIF_IEEE802.3_liaison_19OCt09.pdf

    OIF_IEEE802.3_liaison_19OCt09

    SerU,做网络安全FTP内容的实验必备

    做网络安全FTP内容的实验必备

    nagarajan_01_1107.pdf

    nagarajan_01_1107

    [AB PLC例程源码][MMS_043879]Programming in SFC and ST Language.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    mellitz_3cd_01_0318.pdf

    mellitz_3cd_01_0318

    PyQt6实战派 配套代码

    PyQt6实战派 配套代码

    陕西省省级非物质文化遗产民俗经纬度数据统计表

    陕西省省级非物质文化遗产经纬度数据统计表 统计内容包含以下字段: 1. 项目名称 2. 遗产类别 3. 入选批次 4. 所属地区 5. 申报地区/单位 6. 地理经度 7. 地理纬度 该统计表系统记录了陕西省省级非物质文化遗产的地理空间信息,为文化遗产的数字化保护与研究工作提供了重要的数据支撑。

    ran_3ck_02a_0918.pdf

    ran_3ck_02a_0918

    毕业设计-基于springboot+vue开发的汽车租赁管理系统【源码+sql+可运行】50308.zip

    毕业设计_基于springboot+vue开发的汽车租赁管理系统【源码+sql+可运行】【50308】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码; 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - 业务管理:汽车管理、客户管理、租赁订单 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!

    Runcorder - 跑步训练管理系统

    # Runcorder - 跑步训练管理系统 Runcorder 是一款专为跑步爱好者、马拉松运动员及高校体育生设计的本地化跑步训练管理工具,基于 Python 开发,结合 Tkinter 图形界面与强大的数据处理能力,为用户提供从训练记录到数据分析的全方位支持。无论是初学者还是专业跑者,Runcorder 都能帮助你科学规划训练、精准追踪进度,并通过可视化图表直观呈现训练成果,让你的跑步训练更智能、更高效! - **多用户管理**:支持创建、加载和删除用户档案,每个用户的数据独立存储,确保隐私与安全。 - **科学训练记录**:全维度记录跑步数据,包括日期、里程、配速、自评和晨跑标记,支持智能输入校验,避免数据错误。 - **多维数据分析**:通过动态可视化图表展示跑步里程趋势、平均配速曲线,支持自定义 Y 轴范围,帮助用户深入理解训练效果。 - **高阶功能**:提供 4 种科学训练模式(有氧/无氧/混合),支持历史记录修改与删除,数据以 JSON 格式持久化存储,跨平台兼容。

    paatzsch_01_0708.pdf

    paatzsch_01_0708

Global site tag (gtag.js) - Google Analytics