`

java.util.concurrent详解(二)Semaphore/FutureTask/Exchanger

    博客分类:
  • lock
阅读更多

-----------------------------------------------------------------------------
3. Semaphore
    我们先来学习一下JDK1.5 API中关于这个类的详细介绍:
“一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。”

    我们一般用它来控制某个对象的线程访问对象

    例如,对于某个容器,我们规定,最多只能容纳n个线程同时操作
使用信号量来模拟实现


具体代码如下(参考 [JCIP])

Java代码 复制代码  收藏代码
  1. import  java.util.Collections;   
  2. import  java.util.HashSet;   
  3. import  java.util.Set;   
  4. import  java.util.concurrent.ExecutorService;   
  5. import  java.util.concurrent.Executors;   
  6. import  java.util.concurrent.Semaphore;   
  7.   
  8. public   class  TestSemaphore {   
  9.   
  10.      public   static   void  main(String[] args) {   
  11.         ExecutorService exec = Executors.newCachedThreadPool();   
  12.         TestSemaphore t =  new  TestSemaphore();   
  13.          final  BoundedHashSet<String> set = t.getSet();   
  14.   
  15.          for  ( int  i =  0 ; i <  3 ; i++) { //三个线程同时操作add   
  16.             exec.execute( new  Runnable() {   
  17.                  public   void  run() {   
  18.                      try  {   
  19.                         set.add(Thread.currentThread().getName());   
  20.                     }  catch  (InterruptedException e) {   
  21.                         e.printStackTrace();   
  22.                     }   
  23.                 }   
  24.             });   
  25.         }   
  26.   
  27.          for  ( int  j =  0 ; j <  3 ; j++) { //三个线程同时操作remove   
  28.             exec.execute( new  Runnable() {   
  29.                  public   void  run() {   
  30.                     set.remove(Thread.currentThread().getName());   
  31.                 }   
  32.             });   
  33.         }   
  34.         exec.shutdown();   
  35.     }   
  36.   
  37.      public  BoundedHashSet<String> getSet() {   
  38.          return   new  BoundedHashSet<String>( 2 ); //定义一个边界约束为2的线程   
  39.     }   
  40.   
  41.      class  BoundedHashSet<T> {   
  42.          private   final  Set<T> set;   
  43.          private   final  Semaphore semaphore;   
  44.   
  45.          public  BoundedHashSet( int  bound) {   
  46.              this .set = Collections.synchronizedSet( new  HashSet<T>());   
  47.              this .semaphore =  new  Semaphore(bound,  true );   
  48.         }   
  49.   
  50.          public   void  add(T o)  throws  InterruptedException {   
  51.             semaphore.acquire(); //信号量控制可访问的线程数目   
  52.             set.add(o);   
  53.             System.out.printf( "add:%s%n" ,o);   
  54.         }   
  55.   
  56.          public   void  remove(T o) {   
  57.              if  (set.remove(o))   
  58.                 semaphore.release(); //释放掉信号量   
  59.             System.out.printf( "remove:%s%n" ,o);   
  60.         }   
  61.     }   
  62. }  
[java] view plain copy
  1.   



    总结:Semaphore通常用于对象池的控制

4.FutureTask
    我们先来学习一下JDK1.5 API中关于这个类的详细介绍:

    “取消的异步计算。利用开始和取消计算的方法、查询计算是否完成的方法和获取计算结果的方法,此类提供了对 Future 的基本实现。仅在计算完成时才能获取结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,就不能再重新开始或取消计算。
可使用 FutureTask 包装 Callable 或 Runnable 对象。因为 FutureTask 实现了 Runnable,所以可将 FutureTask 提交给 Executor 执行。
除了作为一个独立的类外,此类还提供了 protected 功能,这在创建自定义任务类时可能很有用。 “

    应用举例:我们的算法中有一个很耗时的操作,在编程的是,我们希望将它独立成一个模块,调用的时候当做它是立刻返回的,并且可以随时取消的

具体代码如下(参考 [JCIP])

Java代码 复制代码  收藏代码
  1. import  java.util.concurrent.Callable;   
  2. import  java.util.concurrent.ExecutionException;   
  3. import  java.util.concurrent.ExecutorService;   
  4. import  java.util.concurrent.Executors;   
  5. import  java.util.concurrent.FutureTask;   
  6.   
  7. public   class  TestFutureTask {   
  8.   
  9.      public   static   void  main(String[] args) {   
  10.         ExecutorService exec=Executors.newCachedThreadPool();   
  11.            
  12.         FutureTask<String> task= new  FutureTask<String>( new  Callable<String>(){ //FutrueTask的构造参数是一个Callable接口   
  13.              @Override   
  14.              public  String call()  throws  Exception {   
  15.                  return  Thread.currentThread().getName(); //这里可以是一个异步操作   
  16.             }});   
  17.                
  18.              try  {   
  19.                 exec.execute(task); //FutureTask实际上也是一个线程   
  20.                 String result=task.get(); //取得异步计算的结果,如果没有返回,就会一直阻塞等待   
  21.                 System.out.printf( "get:%s%n" ,result);   
  22.             }  catch  (InterruptedException e) {   
  23.                 e.printStackTrace();   
  24.             }  catch  (ExecutionException e) {   
  25.                 e.printStackTrace();   
  26.             }   
  27.     }   
  28.   
  29. }  


    总结:FutureTask其实就是新建了一个线程单独执行,使得线程有一个返回值,方便程序的编写

5. Exchanger
    我们先来学习一下JDK1.5 API中关于这个类的详细介绍:
    “可以在pair中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为 SynchronousQueue 的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。 “

    应用举例:有两个缓存区,两个线程分别向两个缓存区fill和take,当且仅当一个满了,两个缓存区交换

    代码如下(参考了网上给的示例   http://hi.baidu.com/webidea/blog/item/2995e731e53ad5a55fdf0e7d.html)

Java代码 复制代码  收藏代码
  1. import  java.util.ArrayList;   
  2. import  java.util.concurrent.Exchanger;   
  3.   
  4. public   class  TestExchanger {   
  5.   
  6.      public   static   void  main(String[] args) {   
  7.          final  Exchanger<ArrayList<Integer>> exchanger =  new  Exchanger<ArrayList<Integer>>();   
  8.          final  ArrayList<Integer> buff1 =  new  ArrayList<Integer>( 10 );   
  9.          final  ArrayList<Integer> buff2 =  new  ArrayList<Integer>( 10 );   
  10.   
  11.          new  Thread( new  Runnable() {   
  12.              @Override   
  13.              public   void  run() {   
  14.                 ArrayList<Integer> buff = buff1;   
  15.                  try  {   
  16.                      while  ( true ) {   
  17.                          if  (buff.size() >=  10 ) {   
  18.                             buff = exchanger.exchange(buff); //开始跟另外一个线程交互数据   
  19.                             System.out.println( "exchange buff1" );   
  20.                             buff.clear();   
  21.                         }   
  22.                         buff.add(( int )(Math.random()* 100 ));   
  23.                         Thread.sleep(( long )(Math.random()* 1000 ));   
  24.                     }   
  25.                 }  catch  (InterruptedException e) {   
  26.                     e.printStackTrace();   
  27.                 }   
  28.             }   
  29.         }).start();   
  30.            
  31.          new  Thread( new  Runnable(){   
  32.              @Override   
  33.              public   void  run() {   
  34.                 ArrayList<Integer> buff=buff2;   
  35.                  while ( true ){   
  36.                      try  {   
  37.                          for (Integer i:buff){   
  38.                             System.out.println(i);   
  39.                         }   
  40.                         Thread.sleep( 1000 );   
  41.                         buff=exchanger.exchange(buff); //开始跟另外一个线程交换数据   
  42.                         System.out.println( "exchange buff2" );   
  43.                     }  catch  (InterruptedException e) {   
  44.                         e.printStackTrace();   
  45.                     }   
  46.                 }   
  47.             }}).start();   
  48.     }   
  49. }  



    总结:Exchanger在特定的使用场景比较有用(两个伙伴线程之间的数据交互)

分享到:
评论

相关推荐

    java并发工具包 java.util.concurrent中文版用户指南pdf

    1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...

    Tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException)

    "java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError" 是一个典型的错误提示,它表明在并发执行过程中遇到了内存不足的问题。下面我们将深入探讨这个问题的原因、影响以及如何解决。 内存溢出...

    java.util.logging.Logger使用详解

    ### Java.util.logging.Logger 使用详解 #### 一、创建Logger对象 在Java中,`java.util.logging.Logger` 是标准的日志框架之一,它提供了基础的日志记录功能。为了使用这一功能,首先需要获得 `java.util.logging...

    Java并发工具包java.util.concurrent用户指南中英文对照阅读版.pdf

    java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...

    java.util.concurrent 学习ppt

    Java.util.concurrent是Java 5.0引入的一个重要包,它为多线程编程提供了一组高级并发工具。这个包的设计者是Doug Lea,它的出现是JSR-166的一部分,也被称作Tiger更新。Java.util.concurrent的引入是为了解决传统...

    java并发工具包 java.util.concurrent中文版pdf

    ### Java并发工具包 `java.util.concurrent` 知识点详解 #### 一、引言 随着多核处理器的普及和应用程序复杂度的增加,多线程编程成为了现代软件开发不可或缺的一部分。为了简化并发编程的复杂性,Java 5 引入了 `...

    java.util.concurrent

    java.util.concurrent总体概览图。 收取资源分3分。需要的同学可以下载一下。 java.util.concurrent主要包括5个部分executor,colletions,locks,atomic,tools。 该图详细的列举了并发包下面的结构,包含所有接口和...

    java多线程学习-java.util.concurrent详解(一) Latch/Barrier

    `java.util.concurrent`包是Java提供的一个强大的多线程工具库,其中包含了许多类和接口,如`CountDownLatch`和`CyclicBarrier`,它们为程序员提供了更高级别的同步和协调机制。这篇文档将详细解析这两个工具类的...

    java.util.Date与java.sql.Date相互转换

    ### Java.util.Date与Java.sql.Date相互转换 #### 知识点概述 在Java开发中,经常需要处理日期和时间相关的操作。Java标准库提供了两个重要的日期类:`java.util.Date` 和 `java.sql.Date`。虽然它们名字相似,但...

    JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用

    "JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用" JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用是Java多线程编程中的一种重要概念。随着多线程编程的普及,线程池的使用变得...

    The java.util.concurrent Synchronizer Framework

    ### Java.util.concurrent.Synchronizer框架详解 #### 一、引言与背景 随着Java技术的发展,多线程编程成为了一项重要的技术需求。为了更好地支持并发编程,Java平台在J2SE 1.5版本中引入了`java.util.concurrent`...

    用java.util.zip包现数据压缩与解压

    ### 使用 Java.util.zip 包实现数据压缩与解压 在计算机科学领域,数据压缩技术是一项重要的功能,它能够帮助减少存储空间的需求以及提高网络传输效率。本文将通过一系列的示例来详细介绍如何利用 Java 中的 `java....

    Java高性能线程库(java.util.concurrent包的补充)

    一个高性能的Java线程库,该库是 JDK 1.5 中的 java.util.concurrent 包的补充,可用于基于并发消息机制的应用。该类库不提供远程的消息功能,其设计的宗旨是实现一个内存中的消息传递机制. 主要特点有: * All ...

    Exception in thread “main“ java.util.InputMismatchException.pdf

    在Java编程语言中,`java.util.InputMismatchException`是一个常见的运行时异常,它通常发生在尝试从数据源(如控制台、文件或数据库)读取数据时,遇到的数据类型与预期的不匹配。在这个特定的场景中,问题出在主线...

    Java并发工具包java.util.concurrent用户指南中英文对照阅读版

    1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...

    java.util.concurrent-多线程框架.docx

    java.util.concurrent 多线程框架 java.util.concurrent 多线程框架是 Java 语言中用于多线程编程的库。该库提供了多种线程池实现、并发集合、同步器、lock 等多种机制,以便开发者更方便地编写高效、可靠的多线程...

    java.util.concurrent.ExecutionException 问题解决方法

    `java.util.concurrent.ExecutionException` 是Java并发编程中一个常见的异常,通常在执行Future对象的get()方法时抛出。这个异常表明在异步任务的执行过程中发生了异常。当我们使用ExecutorService提交任务并尝试...

    动画学习 java.util.concurrent并发工具包

    如何启动:以win7系统为例,最好jdk8 1.打开cmd,cd到jdk的path,本机是:cd C:\Java\jdk6\bin ...java -cp D:\javaConcurrentAnimated.jar vgrazi.concurrent.samples.launcher.ConcurrentExampleLauncher

Global site tag (gtag.js) - Google Analytics