Java并发和多线程:序

  近期,和不少公司的“大牛”聊了聊,当中非常多是关于“并发和多线程”、“系统架构”、“分布式”等方面内容的。
不少问题,感觉自己表达的不够清晰。
   这里面就存在一个“典型问题”和“现象”了:能够依据已有经验和学习能力。把遇到的问题都解决,可是并不能非常好地表达出来。
   
   生活中的非常多事情,都是“相互选择”“相互考察”的双向问题。你站在“甲方”和“乙方”两个立场,推断往往是不同的。


   
   不能改变别人,就努力提高自己。使得自己有很多其它的选择,抱怨这些“不公”是没啥用处的,除了心里舒服一点。
   
   为了解决问题,还是象往常一样。通过一篇篇的文章和代码,总结经验,写点自己的见解。


   
   在解决一个技术问题,看到了JDK API文档中,关于java.util.concurrent并发包的整体介绍。拿来作为“序”还是挺不错的。
   
   java.util.concurrent。在并发编程中非经常常使用的实用工具类,接口有10多个,实现类有20多个。

 
   此包包含了几个小的、已标准化的可扩展框架,以及一些提供实用功能的类。没有这些类,这些功能会非常难实现或实现起来冗长乏味。


   
   以下简要描写叙述基本的组件,另请參阅 locks 和 atomic 包。

 


运行程序
接口。Executor 是一个简单的标准化接口,用于定义相似于线程的自己定义子系统,包含线程池、异步 IO 和轻量级任务框架。


依据所使用的详细 Executor 类的不同,可能在新创建的线程中,现有的任务运行线程中。或者调用 execute() 的线程中运行任务,而且可能顺序或并发运行。
ExecutorService 提供了多个完整的异步任务运行框架。ExecutorService 管理任务的排队和安排。并同意受控制的关闭。
ScheduledExecutorService 子接口及相关的接口加入了对延迟的和定期任务运行的支持。
ExecutorService 提供了安排异步运行的方法。可运行由 Callable 表示的不论什么函数,结果相似于 Runnable。
Future 返回函数的结果。同意确定运行是否完毕,并提供取消运行的方法。
RunnableFuture 是拥有 run 方法的 Future,run 方法运行时将设置其结果。 


实现。类 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 提供可调的、灵活的线程池。


Executors 类提供大多数 Executor 的常见类型和配置的工厂方法,以及使用它们的几种实用工具方法。


其它基于 Executor 的实用工具包含详细类 FutureTask,它提供 Future 的常见可扩展实现,以及 ExecutorCompletionService。它有助于协调对异步任务组的处理。

 


队列
java.util.concurrent ConcurrentLinkedQueue 类提供了高效的、可伸缩的、线程安全的非堵塞 FIFO 队列。
java.util.concurrent 中的五个实现都支持扩展的 BlockingQueue 接口,该接口定义了 put 和 take 的堵塞版本号:LinkedBlockingQueue、ArrayBlockingQueue、SynchronousQueue、PriorityBlockingQueue 和 DelayQueue。


这些不同的类覆盖了生产者-使用者、消息传递、并行任务运行和相关并发设计的大多数常见使用的上下文。
BlockingDeque 接口扩展 BlockingQueue,以支持 FIFO 和 LIFO(基于堆栈)操作。
LinkedBlockingDeque 类提供一个实现。 


计时
TimeUnit 类为指定和控制基于超时的操作提供了多重粒度(包含纳秒级)。


该包中的大多数类除了包含不确定的等待之外,还包含基于超时的操作。


在使用超时的全部情况中,超时指定了在表明已超时前该方法应该等待的最少时间。
在超时发生后,实现会“尽力”检測超时。可是,在检測超时与超时之后再次实际运行线程之间可能要经过不确定的时间。
接受超时期參数的全部方法将小于等于 0 的值视为根本不会等待。要“永远”等待,能够使用 Long.MAX_VALUE 值。

 


同步器
四个类可协助实现常见的专用同步语句。


Semaphore 是一个经典的并发工具。
CountDownLatch 是一个极其简单但又极其经常使用的实用工具。用于在保持给定数目的信号、事件或条件前堵塞运行。
CyclicBarrier 是一个可重置的多路同步点。在某些并行编程风格中非常实用。


Exchanger 同意两个线程在 collection 点交换对象,它在多流水线设计中是实用的。 


并发 Collection
除队列外。此包还提供了设计用于多线程上下文中的 Collection 实现:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、CopyOnWriteArrayList 和 CopyOnWriteArraySet。


当期望很多线程訪问一个给定 collection 时,ConcurrentHashMap 通常优于同步的 HashMap,ConcurrentSkipListMap 通常优于同步的 TreeMap。


当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList 优于同步的 ArrayList。

 
此包中与某些类一起使用的“Concurrent&rdquo前缀;是一种简写,表明与相似的“同步”类有所不同。
比如。java.util.Hashtable 和 Collections.synchronizedMap(new HashMap()) 是同步的,但 ConcurrentHashMap 则是“并发的”。
并发 collection 是线程安全的。可是不受单个排他锁的管理。
在 ConcurrentHashMap 这一特定情况下。它能够安全地同意进行随意数目的并发读取。以及数目可调的并发写入。
须要通过单个锁不同意对 collection 的全部訪问时,“同步”类是非常实用的。其代价是较差的可伸缩性。
在期望多个线程訪问公共 collection 的其它情况中,通常“并发”版本号要更好一些。
当 collection 是未共享的。或者仅保持其它锁时 collection 是可訪问的情况下,非同步 collection 则要更好一些。 


大多数并发 Collection 实现(包含大多数 Queue)与常规的 java.util 约定也不同,由于它们的迭代器提供了弱一致的,而不是高速失败的遍历。
弱一致的迭代器是线程安全的。可是在迭代时没有必要冻结 collection。所以它不一定反映自迭代器创建以来的全部更新。 


内存一致性属性
Java Language Specification 第 17 章定义了内存操作(如共享变量的读写)的 happen-before 关系。仅仅有写入操作 happen-before 读取操作时,才保证一个线程写入的结果对还有一个线程的读取是可视的。
synchronized 和 volatile 构造 happen-before 关系,Thread.start() 和 Thread.join() 方法形成 happen-before 关系。尤其是: 
线程中的每一个操作 happen-before 稍后按程序顺序传入的该线程中的每一个操作。

 


一个解除锁监视器的(synchronized 堵塞或方法退出)happen-before 同样监视器的每一个兴许锁(synchronized 堵塞或方法进入)。
而且由于 happen-before 关系是可传递的,所以解除锁定之前的线程的全部操作 happen-before 锁定该监视器的不论什么线程兴许的全部操作。

 
写入 volatile 字段 happen-before 每一个兴许读取同样字段。

volatile 字段的读取和写入与进入和退出监视器具有相似的内存一致性效果,但不 须要相互排斥锁。 
在线程上调用 start happen-before 已启动的线程中的不论什么线程。

 
线程中的全部操作 happen-before 从该线程上的 join 成功返回的不论什么其它线程。 


java.util.concurrent 中全部类的方法及其子包扩展了这些对更高级别同步的保证。尤其是: 
线程中将一个对象放入不论什么并发 collection 之前的操作 happen-before 从还有一线程中的 collection 訪问或移除该元素的兴许操作。

 
线程中向 Executor 提交 Runnable 之前的操作 happen-before 其运行開始。同样适用于向 ExecutorService 提交 Callables。

 
异步计算(由 Future 表示)所採取的操作 happen-before 通过还有一线程中 Future.get() 获取结果兴许的操作。

 
“释放”同步储存方法(如 Lock.unlock、Semaphore.release 和 CountDownLatch.countDown)之前的操作 happen-before 还有一线程中同样同步储存对象成功“获取”方法(如 Lock.lock、Semaphore.acquire、Condition.await 和 CountDownLatch.await)的兴许操作。
对于通过 Exchanger 成功交换对象的每一个线程对。每一个线程中 exchange() 之前的操作 happen-before 还有一线程中相应 exchange() 兴许的操作。

 
调用 CyclicBarrier.await 之前的操作 happen-before 屏障操作所运行的操作。屏障操作所运行的操作 happen-before 从还有一线程中相应 await 成功返回的兴许操作。 


  对于“happen-before”等地方。还没全然搞懂,须要时间消化。
   可參考:http://ifeve.com/easy-happens-before/。http://mapserver000-gmail-com.iteye.com/blog/1945688
  
  江湖传言,《Java并发编程实践》这本书还是非常不错的,2016年买本读读。近期先多研究点代码层次的东东。


   
  

原文地址:https://www.cnblogs.com/claireyuancy/p/7348950.html