转载自http://janeky.iteye.com/blog/770393

-----------------------------------------------------------------------------

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[转载] java多线程学习-java.util.concurrent详解(二)Semaphore/FutureTask/Exchanger的更多相关文章

  1. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  2. Shell学习之Bash变量详解(二)

    Shell学习之Bash变量详解 目录 Bash变量 Bash变量注意点 用户自定义变量 环境变量 位置参数变量 预定义变量 Bash变量 用户自定义变量:在Bash中由用户定义的变量. 环境变量:这 ...

  3. [转载] java多线程学习-java.util.concurrent详解(一) Latch/Barrier

    转载自http://janeky.iteye.com/blog/769965     Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可 ...

  4. [转载] java多线程学习-java.util.concurrent详解(四) BlockingQueue

    转载自http://janeky.iteye.com/blog/770671 ------------------------------------------------------------- ...

  5. [转载] java多线程学习-java.util.concurrent详解(三)ScheduledThreadPoolExecutor

    转载自http://janeky.iteye.com/blog/770441 ------------------------------------------------------------- ...

  6. java多线程学习--java.util.concurrent (转载)

    题记:util和concurrent 包是后续重点先看的和学习的模块 原文地址:http://www.cnblogs.com/sunhan/p/3817806.html CountDownLatch, ...

  7. java多线程学习--java.util.concurrent

    CountDownLatch,api 文档:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.h ...

  8. java并发包java.util.concurrent详解

    线程池ThreadPoolExecutor的使用 并发容器之CopyOnWriteArrayList 并发容器之CopyOnWriteArraySet 数据结构之ConcurrentHashMap,区 ...

  9. Java多线程Callable和Future类详解

         public interface Callable<V>    返回结果并且可能抛出异常的任务.实现者定义了一个不带任何参数的叫做 call 的方法      public in ...

随机推荐

  1. iOS开发注意事项(一)

    1.OC的消息机制与C++等的函数(方法)有很大的不同,OC在运行时所执行的代码由运行环境来决定,而C++等则由编译器决定.如果调用的函数是多态的,C++在运行时要按照虚方法表来查出到底执行哪个函数, ...

  2. ASP.NET没有魔法——ASP.NET MVC 与数据库大集合

    ASP.NET没有魔法——ASP.NET与数据库 ASP.NET没有魔法——ASP.NET MVC 与数据库之MySQL ASP.NET没有魔法——ASP.NET MVC 与数据库之ORM ASP.N ...

  3. 一些实用的JQuery代码片段收集(筛选,搜索,样式,清除默认值,多选等)

    //each遍历文本框 清空默认值 $(".maincenterul1").find("input,textarea").each(function () { ...

  4. Java可变参数以及一个简单应用

    可变参数: Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理. 注意:可变参数必须位于最后一项. 原因:当可变参数个数多余一个时,必将有一个不 ...

  5. 不使用数据结构反转栈 递归 CVTE实习 CVTE是一家什么公司

    本文因为垃圾csdn标题字限制,标题写不好.本文想说一个算法,和我在CVTE的实习,我看到CVTE是一家什么公司.如果想要喷我的,可以留言,我不会理.如果想喷公司,可以在博客评论或发到我邮件linde ...

  6. linux命令行下svn常用命令

    linux命令行下svn常用命令 1. 将文件checkout到本地目录 1 #path是服务器上的目录 2 svn checkout path 3 4 #示例 5 svn checkout svn: ...

  7. Java基础(00)

    Java发展史 Java之父:詹姆斯.高斯林(James Gosling). SUN(Stanford University Network 斯坦福大学网络公司)产物. 1995年5月23日,java ...

  8. json_encode()中文不转码

    php使用json_encode()把数组转换为json的时候,总会把中文进行转码,转码后从json数据上我们无法看出其中的中文文字.php5.4以后,当json_encode()的第二个参数赋值为J ...

  9. Linux系统LVM基本使用

    一.关于LVM的几个概念 1. LVM:逻辑卷管理器,是建立在物理存储设备上的一个抽象层,允许你生成逻辑存储卷, 与硬件相关的存储设置被其隐藏,你不用停止应用或卸载文件系统来调整卷大小 或迁移数据,可 ...

  10. 解析 .Net Core 注入 (3) 创建对象

    回顾 通过前两节的学习,我们知道 IServiceCollection 以元数据(ServiceDescriptor)的形式存放着用户注册的服务,它的 IServiceCollection 的拓展方法 ...