归档之于 ‘ 2013 年11月 ’
测试并发应用(三)监控Executor框架
声明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 译者:郑玉婷
监控Executor框架
Executor 框架提供从线程的创建和管理来分别实现任务来执行这些任务的机制。如果你使用一个执行者,你只需要实现 Runnable 对象并把他们发送给执行者。 执行者的责任是管理线程。当你发一个任务给执行者,它会尝试使用pooled线程来执行这个任务,来避免创建新的任务。此机制由 Executor 接口提供,它是以 ThreadPoolExecutor 类来实现的。
在这个指南,你将学习从ThreadPoolExecutor执行者可以获取的信息和如何获取这些信息。 阅读全文
happens-before俗解
学习Java并发,到后面总会接触到happens-before偏序关系。初接触玩意儿简直就是不知所云,下面是经过一段时间折腾后个人对此的一点浅薄理解,希望对初接触的人有帮助。如有不正确之处,欢迎指正。
synchronized、大部分锁,众所周知的一个功能就是使多个线程互斥/串行的(共享锁允许多个线程同时访问,如读锁)访问临界区,但他们的第二个功能 —— 保证变量的可见性 —— 常被遗忘。
为什么存在可见性问题?简单介绍下。相对于内存,CPU的速度是极高的,如果CPU需要存取数据时都直接与内存打交道,在存取过程中,CPU将一直空闲,这是一种极大的浪费,妈妈说,浪费是不好的,所以,现代的CPU里都有很多寄存器,多级cache,他们比内存的存取速度高多了。某个线程执行时,内存中的一份数据,会存在于该线程的工作存储中(working memory,是cache和寄存器的一个抽象,这个解释源于《Concurrent Programming in Java: Design Principles and Patterns, Second Edition》§2.2.7,原文:Every thread is defined to have a working memory (an abstraction of caches and registers) in which to store values. 有不少人觉得working memory是内存的某个部分,这可能是有些译作将working memory译为工作内存的缘故,为避免混淆,这里称其为工作存储,每个线程都有自己的工作存储),并在某个特定时候回写到内存。单线程时,这没有问题,如果是多线程要同时访问同一个变量呢?内存中一个变量会存在于多个工作存储中,线程1修改了变量a的值什么时候对线程2可见?此外,编译器或运行时为了效率可以在允许的时候对指令进行重排序,重排序后的执行顺序就与代码不一致了,这样线程2读取某个变量的时候线程1可能还没有进行写入操作呢,虽然代码顺序上写操作是在前面的。这就是可见性问题的由来。
第一届淘宝并发编程比赛-多线程排序性能优化
去年一粟在淘宝内部组织了第一届淘宝并发编程比赛。
具体比赛问题请移步这里:https://github.com/Skinney/WordSorter 查看。
里面已经有可运行的代码,在一粟的机器上(RMBP 2012: 2.7 GHz Intel Core i7)运行速度如下:
[code]
16:07:49 hugo-rmbp ~/Projects/hugozhu/WordSorter/Go $ go run main.go 128 sowpods.txt out.txt
WordSort finished in <strong>335 ms</strong>
16:07:19 hugo-rmbp ~/Projects/hugozhu/WordSorter/Java $ java Sort 128 sowpods.txt out.txt
Loading contents of sowpods.txt… 170ms
Sorting… 222ms
Writing results to out.txt… 135ms
Using 128 threads, 267751 words was sorted in <strong>528</strong> milliseconds.
[/code]
Java落后很多, 但看实现I/O部分耗费了一半多的时间,我们可以来优化一下Java实现:提高一下I/O性能,或者试一下Fork/Join框架,请大家都试试,把优化结果贴上来比较。 阅读全文