concurrent包

 参考博文:http://www.cnblogs.com/sarafill/archive/2011/05/18/2049461.html

                   http://blog.csdn.net/wulei_longhe/article/details/30032031

JDK 5.0 中的并发改进可以分为三组:
    • JVM 级别更改。大多数现代处理器对并发提供某一硬件级别的支持,通常以 compare-and-swap (CAS)指令形式。CAS 是一种低级别的、细粒度的技术,它允许多个线程更新一个内存位置,同时能够检测其他线程的冲突并进行恢复。它是许多高性能并发算法的基础。在 JDK 5.0 之前,Java 语言中用于协调线程之间的访问的惟一原语是同步,同步是更重量级和粗粒度的。 CAS 可以开发高度可伸缩的并发 Java 类。这些更改主要由 JDK 库类使用,而不是由开发人员使用。
    • 低级实用程序类 -- 锁定和原子类。使用 CAS 作为并发原语,ReentrantLock 类提供与 synchronized 原语相同的锁定和内存语义,然而这样可以更好地控制锁定(如计时的锁定等待、锁定轮询和可中断的锁定等待)和提供更好的可伸缩性(竞争时的高性能)。大多数开发人员将不再直接使用 ReentrantLock 类,而是使用在 ReentrantLock 类上构建的高级类。
    • 高级实用程序类。这些类实现并发构建块,每个计算机科学文本中都会讲述这些类 -- 信号、互斥、闩锁、屏障、交换程序、线程池和线程安全集合类等。大部分开发人员都可以在应用程序中用这些类,来替换许多(如果不是全部)同步、wait() 和 notify() 的使用,从而提高性能、可读性和正确性。


一、Semaphore-计数信号量

      从概念上讲,信号量维护了一个许可集。通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。acquire()表示可以从信号量获取一个许可,提供之前线程将会阻塞。release()表示释放许可,并返回给信号量。用法如下:

01 import java.util.concurrent.ExecutorService;
02 import java.util.concurrent.Executors;
03 import java.util.concurrent.Semaphore;
04 public class MySemaphoreextends Thread {
05 Semaphore position;
06 private int id;
07 public MySemaphore(int i,Semaphore s){
08     this.id=i;
09     this.position=s;
10 }
11 public void run(){
12     try{
13      if(position.availablePermits()>0){
14       System.out.println("顾客["+this.id+"]进入厕所,有空位");
15      }
16      else{
17       System.out.println("顾客["+this.id+"]进入厕所,没空位,排队");
18      }
19      position.acquire();
20      System.out.println("顾客["+this.id+"]获得坑位");
21      Thread.sleep((int)(Math.random()*1000));
22      System.out.println("顾客["+this.id+"]使用完毕");
23      position.release();
24     }
25     catch(Exception e){
26      e.printStackTrace();
27     }
28 }
29 public static void main(String args[]){
30     ExecutorService list=Executors.newCachedThreadPool();
31     Semaphore position=new Semaphore(2);
32     for(int i=0;i<10;i++){
33      list.submit(new MySemaphore(i+1,position));
34     }
35     list.shutdown();
36     position.acquireUninterruptibly(2);
37     System.out.println("使用完毕,需要清扫了");
38     position.release(2);
39 }
40 }

二、CompletionService

将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果,即使用 Producer/Consumer 模式,其中生产者创建任务并提交,消费者请求完成任务的结果并处理这些结果。CompletionService 依赖于一个单独的 Executor 来实际执行任务,在这种情况下,CompletionService 只管理一个内部完成队列。ExecutorCompletionService 类提供了此方法的一个实现。用法如下:

01 import java.util.concurrent.Callable;
02 import java.util.concurrent.CompletionService;
03 import java.util.concurrent.ExecutorCompletionService;
04 import java.util.concurrent.ExecutorService;
05 import java.util.concurrent.Executors;
06 public class MyCompletionServiceimplements Callable<String> {
07 private int id;
08  
09 public MyCompletionService(int i){
10    this.id=i;
11 }
12 public static void main(String[] args) throws Exception{
13    ExecutorService service=Executors.newCachedThreadPool();
14    CompletionService<String> completion=new ExecutorCompletionService<String>(service);
15    for(int i=0;i<10;i++){
16     completion.submit(new MyCompletionService(i));
17    }
18    for(int i=0;i<10;i++){
19     System.out.println(completion.take().get());
20    }
21    service.shutdown();
22 }
23 public String call() throws Exception {
24    Integer time=(int)(Math.random()*1000);
25    try{
26     System.out.println(this.id+" start");
27     Thread.sleep(time);
28     System.out.println(this.id+" end");
29    }
30    catch(Exception e){
31     e.printStackTrace();
32    }
33    return this.id+":"+time;
34 }
35 }

三、CountdownLatch

有两个重要的方法:

await():使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断

countDown():递减锁存器的计数,如果计数到达零,则释放所有等待的线程

下面以模拟运动员比赛说明用法:

import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.Executor;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
 
  public class CountDownLatchDemo {
     private static final int PLAYER_AMOUNT = 5;
     public CountDownLatchDemo() {
         // TODO Auto-generated constructor stub    
      }
     /**
      * @param args
      */
     public static void main(String[] args) {
         // TODO Auto-generated method stub
         //对于每位运动员,CountDownLatch减1后即结束比赛
         CountDownLatch begin = new CountDownLatch(1);
         //对于整个比赛,所有运动员结束后才算结束
         CountDownLatch end = new CountDownLatch(PLAYER_AMOUNT);
         Player[] plays = new Player[PLAYER_AMOUNT];
         
         for(int i=0;i<PLAYER_AMOUNT;i++)
             plays[i] = new Player(i+1,begin,end);
         

//设置特定的线程池,大小为5

ExecutorService exe = Executors.newFixedThreadPool(PLAYER_AMOUNT); for(Player p:plays) exe.execute(p); //分配线程 System.out.println("Race begins!"); begin.countDown(); try{ end.await(); //等待end状态变为0,即为比赛结束 }catch (InterruptedException e) { // TODO: handle exception e.printStackTrace(); }finally{ System.out.println("Race ends!"); } exe.shutdown(); } }
public class Player implements Runnable {
 
     private int id;
     private CountDownLatch begin;
     private CountDownLatch end;
     public Player(int i, CountDownLatch begin, CountDownLatch end) {
         // TODO Auto-generated constructor stub
         super();
         this.id = i;
         this.begin = begin;
         this.end = end;
     }
 
     @Override
     public void run() {
         // TODO Auto-generated method stub
         try{
             begin.await();        //等待begin的状态为0
             Thread.sleep((long)(Math.random()*100));    //随机分配时间,即运动员完成时间
             System.out.println("Play"+id+" arrived.");
         }catch (InterruptedException e) {
             // TODO: handle exception
             e.printStackTrace();
         }finally{
             end.countDown();    //使end状态减1,最终减至0
         }
     }
 }

四、CyclicBarrier

允许一组线程互相等待,直到所有子线程都到达了这个屏障时,再一起继续执行后面的动作。
两个重要方法:

await():在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待

getParties():返回要求启动此 barrier 的参与者数目

下面举例来说明用法:

年末公司组织团建,要求每一位员工周六上午8点【自驾车】到公司门口集合,然后【自驾车】前往目的地。 在这个案例中,公司作为主线程,员工作为子线程。

package com.test.spring.support;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/** 
 * @author  javaloveiphone
 * @date 创建时间:2017年1月25日 上午10:59:11 
 * @Description: 
 */
public class Company {
    public static void main(String[] args) throws InterruptedException {

        //员工数量
        int count = 5;
        //创建计数器
        CyclicBarrier barrier = new CyclicBarrier(count+1);

        //创建线程池,可以通过以下方式创建
        //ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1,1,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(count));
        ExecutorService threadPool =  Executors.newFixedThreadPool(count);

        System.out.println("公司发送通知,每一位员工在周六早上8点【自驾车】到公司大门口集合");
        for(int i =0;i<count ;i++){
            //将子线程添加进线程池执行
            threadPool.execute(new Employee(barrier,i+1));
            Thread.sleep(10);
        }
        try {
            //阻塞当前线程,直到所有员工到达公司大门口之后才执行
            barrier.await();
            Thread.sleep(10);
            // 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
            //latch.await(long timeout, TimeUnit unit)
            System.out.println("所有员工已经到达公司大门口,公司领导一并【自驾车】同员工前往活动目的地。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }finally{
            //最后关闭线程池,但执行以前提交的任务,不接受新任务
            threadPool.shutdown();
            //关闭线程池,停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
            //threadPool.shutdownNow();
        }
    }
}

//分布式工作线程
class Employee implements Runnable{

    private CyclicBarrier barrier;
    private int employeeIndex;

    public Employee(CyclicBarrier barrier,int employeeIndex){
        this.barrier = barrier;
        this.employeeIndex = employeeIndex;
    }

    @Override
    public void run() {
        try {
            System.out.println("员工:"+employeeIndex+",正在前往公司大门口集合...");
            Thread.sleep(10*employeeIndex);
            System.out.println("员工:"+employeeIndex+",已到达。");
            barrier.await();
            Thread.sleep(10);
            System.out.println("员工:"+employeeIndex+",【自驾车】前往目的地");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
公司发送通知,每一位员工在周六早上8点【自驾车】到公司大门口集合
员工:1,正在前往公司大门口集合...
员工:1,已到达。
员工:2,正在前往公司大门口集合...
员工:3,正在前往公司大门口集合...
员工:2,已到达。
员工:4,正在前往公司大门口集合...
员工:5,正在前往公司大门口集合...
员工:3,已到达。
员工:4,已到达。
员工:5,已到达。
员工:3,【自驾车】前往目的地
员工:5,【自驾车】前往目的地
所有员工已经到达公司大门口,公司领导一并【自驾车】同员工前往活动目的地。
员工:4,【自驾车】前往目的地
员工:1,【自驾车】前往目的地
员工:2,【自驾车】前往目的地


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值