一、java.util.concurrent.Exchanger
Java 5中新增加了一个Exchanger类,这个类可以用来在一对线程之间交换元素,并且这种交换是线程安全的,不需要同步,具体说来就是每个线程将它想交换的对象放到exchanger对象中去,然后从这个对象返回对方线程用来交换的对象。有一点要求就是这两个交换的对象类型必须相同。
例如要实现生产者、消费者应用,以前可能的一种作法就是用一个集合:一个线程往里写,另一个线程从里面读。现在,如果用Exchanger的方式,那可以用两个集合,一个用在生产端,一个用在消费端,然后不时的对他们进行交换,例如:
Exchanger<List<String>> exchanger = new Exchanger<List<String>>(); Producer producer = new Producer(exchanger); Consumer consumer = new Consumer(exchanger); producer.start(); consumer.start();
首先创建一个Exchanger对象,并指定了它将交换的内容格式,然后分别创建Producer对象和Consumer对象,并将此Exchanger对象传入。Producer类实现如下:
class Producer extends Thread{ private Exchanger<List<String>> exchanger; private List<String> storage = new ArrayList<String>(); public Producer(Exchanger<List<String>> e){ this.exchanger = e; } @Override public void run() { int i = 0; while(true){ //store something into storage storage.add("One"+i); storage.add("two"+i); storage.add("three"+i); try { //show the storage before exchange System.out.println("Produced "+storage); //exchange with consumer, and get the exchanged from it storage = exchanger.exchange(storage); //show the exchanged result System.out.println("After exchanged on Producer: "+storage); //sleep for a while before continue sleep(2000); i++; } catch (InterruptedException e) { e.printStackTrace(); } } } }
它会不间断的生产,并且每次生产的内容都不一样,然后将生产的东西进行交换。它并不需要知道有谁在和它交换,只要将要交换的内容传给Exchanger,并从Exchanger取会交换的结果。Consumer的实现如下:
class Consumer extends Thread{ private Exchanger<List<String>> exchanger; private List<String> storage = new ArrayList<String>(); public Consumer(Exchanger<List<String>> e){ this.exchanger = e; } @Override public void run() { while(true){ try { /* * do exchange, the storage is empty before exchanged * and will be exchanged to producer */ storage = exchanger.exchange(storage); //show the exchanged result System.out.println("Consumed: "+storage); System.out.println("======================================"); /* * remember to reset storage before continue, else the values * will be back to producer side */ storage.clear(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
执行过程和Producer类似,不过需要注意的是:在每次使用完交换来的内容后,要记得清空,要不然结果又会被交换回Producer端。以上程序某次运行的结果可能如下:
Produced [One0, two0, three0] After exchanged on Producer: [] Consumed: [One0, two0, three0] ====================================== Produced [One1, two1, three1] After exchanged on Producer: [] Consumed: [One1, two1, three1] ====================================== Produced [One2, two2, three2] After exchanged on Producer: [] Consumed: [One2, two2, three2] ======================================
二、分支/合并(Fork/Join)框架
Java 7提供了一个分支/合并(Fork/Join)框架,它的作者是Doug Lea,实现来源于他于2000年发表的一篇论文:http://gee.cs.oswego.edu/dl/papers/fj.pdf 。简单的说就是:Fork -- 将大任务分解成一系列小任务分别执行,每个小任务由一个线程执行; Join -- 在每个小任务执行完成后,将它们的结果合并,得到最终的结果。(我不太清楚它和最近比较流行的Mapper/Reduce编程模式有多大的不同)
要使用Fork/Join框架,涉及到以下几个主要的类:
- ForkJoinPool:这是ForkJoin任务执行线程所在的线程池,由它创建一系统的线程去执行每个小任务。可以指定初始的并发数,如果不指定,由默认值为当前机器的内核数,这个可以从源码里得出:Runtime.getRuntime().availableProcessors()。
- ForkJoinTask:这是ForkJoin任务的抽象实现,一般不直接继承它,而是使用它的以下两个抽象子类。
- RecursiveAction:ForkJoinTask的子类,一般用于没有返回值的情况
- RecursiveTask:ForkJoinTask的子类,一般用于有返回值的情况
其中ForkJoinPool有三个用来提交或开始任务的方法:
- submit:异步的执行Task,并且在任务结束后,可以使用getRawResult()方法获取返回值;在获取返回值之前,可能需要使用如 is*() 方法判断当前任务的执行结果。
- execute:同submit类似,但是不带返回值
- invoke:同submit类似,但是是同步的,即方法会在任务结果里才返回。可以看它的源码实现,返回task.join()或者task.invoke()。
相关推荐
本书的新版本展示了如何利用Java线程工具的全部优势,并介绍了JDK 2线程接口中的最新变化。你将学习如何使用线程来提高效率,如何有效地使用它们,以及如何避免常见的错误。本书讨论了死锁、竞态条件以及饥饿等问题...
Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解
JAVA 线程类应用JAVA 线程类应用JAVA 线程类应用JAVA 线程类应用JAVA 线程类应用JAVA 线程类应用JAVA 线程类应用JAVA 线程类应用JAVA 线程类应用
Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...
Java线程Java线程Java线程Java线程Java线程Java线程
java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-...
java 线程Dump 分析工具: Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的...
Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...
Java线程模块Java线程之秒表新手学习Java线程模块时,利用Java中设置线程的暂停间隔,做的简易秒表
java线程同步java线程同步java线程同步
用反射实现了对java线程简单的封装,类似c#线程,使用此封装类勿需再次继承Thread类或实现Runnable接口,直接绑定需要使用线程的方法即可,另支持动态传参,如觉着好用请多多支持作者 QQ 359103820 希望能为使用线程...
java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...
Java的线程和Java AppletJava的线程和Java AppletJava的线程和Java AppletJava的线程和Java AppletJava的线程和Java Applet
java线程.pdf java 学习java
在Java出现以前,似乎人人都在谈论线程,却很少有人使用它。用线程编程是技巧性很强的且不可移植。 而在Java中却完全不同。Java的线程工具易于使用,并且像Java中的其他东西一样可以在不同的平台之间移植。这是一件...
java 线程 新手java 线程 新手java 线程 新手java 线程 新手
分析java线程日志的工具,使用jstack把java线程日志dump下来,然后上传到该工具,就可以查看线程阻塞情况等信息。
Java 模拟线程并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发