Richard_

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1.Java.util.concurrent包下的类:参考自(https://blog.csdn.net/axi295309066/article/details/65665090

  1.1阻塞队列BolockingQueue

  BlockingQueue 通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。下图是对这个原理的阐述:

blocking-queue

  •   一个线程往里边放,另外一个线程从里边取的一个 BlockingQueue。
  •   一个线程将会持续生产新对象并将其插入到队列之中,直到队列达到它所能容纳的临界点。也就是说,它是有限的。如果该阻塞队列到达了其临界点,负责生产的线程将会在往里边插入新对象时发  生阻塞。它会一直处于阻塞之中,直到负责消费的线程从队列中拿走一个对象。
  •   负责消费的线程将会一直从该阻塞队列中拿出对象。如果消费线程尝试去从一个空的队列中提取对象的话,这个消费线程将会处于阻塞之中,直到一个生产线程把一个对象丢进队列。

2.并发Map: ConcurrentMap

 ConcurrentHashMap

  2.1 ConcurrentHashMap 和 java.util.HashTable 类很相似,但 ConcurrentHashMap 能够提供比 HashTable 更好的并发性能。在你从中读取对象的时候 ConcurrentHashMap 并不会把整个 Map 锁住。此外,  在你向其中写入对象的时候,ConcurrentHashMap 也不会锁住整个 Map。它的内部只是把 Map 中正在被写入的部分进行锁定。

  2.2 另外一个不同点是,在被遍历的时候,即使是 ConcurrentHashMap 被改动,它也不会抛ConcurrentModificationException。尽管 Iterator 的设计不是为多个线程的同时使用。

 

3.信号量 Semaphore

  3.1 java.util.concurrent.Semaphore 类是一个计数信号量。这就意味着它具备两个主要方法:acquire(); release()

  3.2 计数信号量由一个指定数量的 “许可” 初始化。每调用一次 acquire(),一个许可会被调用线程取走。每调用一次 release(),一个许可会被返还给信号量。因此,在没有任何 release() 调用时,最多有 N 个线  程能够通过 acquire() 方法,N 是该信号量初始化时的许可的指定数量。这些许可只是一个简单的计数器。这里没啥奇特的地方。

  3.3 信号量主要有两种用途:

  • 保护一个重要(代码)部分防止一次超过 N 个线程进入
  • 在两个线程之间发送信号

  3.4 公平性

    没有办法保证线程能够公平地可从信号量中获得许可。也就是说,无法担保掉第一个调用 acquire() 的线程会是第一个获得一个许可的线程。如果第一个线程在等待一个许可时发生阻塞,而第二个线程  前来索要一个许可的时候刚好有一个许可被释放出来,那么它就可能会在第一个线程之前获得许可。 如果你想要强制公平,Semaphore 类有一个具有一个布尔类型的参数的构造子,通过这个参数以告知   Semaphore 是否要强制公平。强制公平会影响到并发性能,所以除非你确实需要它否则不要启用它。

  以下是如何在公平模式创建一个 Semaphore 的示例:

  Semaphore semaphore = new Semaphore(1, true); 

4.执行器服务 ExecutorService
java.util.concurrent.ExecutorService 接口表示一个异步执行机制,使我们能够在后台执行任务。因此一个 ExecutorService 很类似于一个线程池。实际上,
存在于 java.util.concurrent 包里的 ExecutorService 实现就是一个线程池实现。

  以下是一个简单的 ExecutorService 例子:

1 ExecutorService executorService = Executors.newFixedThreadPool(10);  
2 
3 executorService.execute(new Runnable() {  
4     public void run() {  
5         System.out.println("Asynchronous task");  
6     }  
7 });  
8 
9 executorService.shutdown();  

  首先使用 newFixedThreadPool() 工厂方法创建一个 ExecutorService。这里创建了一个十个线程执行任务的线程池。
  然后,将一个 Runnable 接口的匿名实现类传递给 execute() 方法。这将导致 ExecutorService 中的某个线程执行该 Runnable。

  *通过submit(Runnable)方法来运行任务与execute类似,submit(Runnable) 方法也要求一个 Runnable 实现类,但它返回一个 Future 对象。这个 Future 对象可以用来检查 Runnable 是否已经执行完毕。

 

5.ScheduledExecutorService

  java.util.concurrent.ScheduledExecutorService 是一个 ExecutorService, 它能够将任务延后执行,或者间隔固定时间多次执行。 任务由一个工作者线程异步执行,而不是由提交任务给       ScheduledExecutorService 的那个线程执行。

 1 ScheduledExecutorService scheduledExecutorService =  
 2         Executors.newScheduledThreadPool(5);  
 3 
 4 ScheduledFuture scheduledFuture =  
 5     scheduledExecutorService.schedule(new Callable() {  
 6         public Object call() throws Exception {  
 7             System.out.println("Executed!");  
 8             return "Called!";  
 9         }  
10     },  
11     5,  
12     TimeUnit.SECONDS); 

首先一个内置 5 个线程的 ScheduledExecutorService 被创建。之后一个 Callable 接口的匿名类示例被创建然后传递给 schedule() 方法。后边的俩参数定义了 Callable 将在 5 秒钟之后被执行。*正如 ExecutorService,在你使用结束之后你需要把 ScheduledExecutorService 关闭掉。否则他将导致 JVM 继续运行,即使所有其他线程已经全被关闭。你可以使用从 ExecutorService 接口继承来的 shutdown() 或 shutdownNow() 方法将 ScheduledExecutorService 关闭。参见 ExecutorService 关闭部分以获取更多信息。

 

6.读写锁 ReadWriteLock

java.util.concurrent.locks.ReadWriteLock 读写锁是一种先进的线程锁机制。它能够允许多个线程在同一时间对某特定资源进行读取,但同一时间内只能有一个线程对其进行写入。

读写锁的理念在于多个线程能够对一个共享资源进行读取,而不会导致并发问题。并发问题的发生场景在于对一个共享资源的读和写操作的同时进行,或者多个写操作并发进行。

本节只讨论 Java 内置 ReadWriteLock。如果你想了解 ReadWriteLock 背后的实现原理,请参考我的《Java 并发指南》主题中的《读写锁》小节。

ReadWriteLock 锁规则

一个线程在对受保护资源在读或者写之前对 ReadWriteLock 锁定的规则如下:
读锁:如果没有任何写操作线程锁定 ReadWriteLock,并且没有任何写操作线程要求一个写锁(但还没有获得该锁)。因此,可以有多个读操作线程对该锁进行锁定。

写锁:如果没有任何读操作或者写操作。因此,在写操作的时候,只能有一个线程对该锁进行锁定。

ReadWriteLock 实现

ReadWriteLock 是个接口,如果你想用它的话就得去使用它的实现类之一。java.util.concurrent.locks 包提供了 ReadWriteLock 接口的以下实现类:ReentrantReadWriteLock

ReadWriteLock 代码示例

以下是 ReadWriteLock 的创建以及如何使用它进行读、写锁定的简单示例代码:

 1 ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
 2 
 3 readWriteLock.readLock().lock();  
 4 
 5 // multiple readers can enter this section  
 6 // if not locked for writing, and not writers waiting  
 7 // to lock for writing.  
 8 
 9 readWriteLock.readLock().unlock();  
10 
11 readWriteLock.writeLock().lock();  
12 
13 // only one writer can enter this section,  
14 // and only if no threads are currently reading.  
15 
16 readWriteLock.writeLock().unlock();

 

posted on 2019-02-22 14:31  Richard_  阅读(132)  评论(0编辑  收藏  举报