一、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 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具...
本书的新版本展示了如何利用Java线程工具的全部优势,并介绍了JDK 2线程接口中的最新变化。你将学习如何使用线程来提高效率,如何有效地使用它们,以及如何避免常见的错误。本书讨论了死锁、竞态条件以及饥饿等问题...
java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类....
根据提供的信息,我们可以推断出这份文档主要关注的是Java线程的相关内容。下面将围绕“Java线程”这一主题展开详细的介绍与解释。 ### Java线程基础 在Java语言中,线程是程序执行流的基本单元。一个标准的Java...
Java线程类应用是Java编程中的重要组成部分,它关乎到多任务处理和程序并发执行的能力。在Java中,线程是程序执行的最小单位,它允许一个程序中有多个执行流同时进行,使得程序能更高效地利用系统资源,特别是在处理...
Java线程有10个优先级(MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY),默认优先级是NORM_PRIORITY。但是,线程优先级并不保证绝对的执行顺序,操作系统调度策略可能影响实际执行顺序。 7. join()方法: 一个线程...
Java线程是并发编程的核心部分,它允许程序在同一时间执行多个独立的任务,从而提高系统效率和响应速度。本文将深入探讨Java线程的概念、生命周期、实现方式以及相关的同步机制。 首先,理解线程的基本概念至关重要...
java 线程Dump 分析工具: Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的...
通过学习这个Java线程使用教程,你将能够熟练地在多线程环境中编写高效、安全的Java程序,理解线程同步、通信、线程池以及并发工具类的使用。阅读提供的"Java线程.pdf"和"说明.txt"文件将帮助你更深入地掌握这些知识...
Java线程是Java编程中的重要概念,特别是在多核处理器和并发处理中不可或缺。Java线程允许程序在同一时间执行多个不同的任务,从而提高了程序的效率和响应性。在燕山大学信息学院计算机系的课程中,李峰教授讲解了...
Java线程是多任务编程的重要概念,它允许程序同时执行多个独立的任务,从而提高系统效率和响应速度。在Java中,线程可以分为用户线程和守护线程,前者是程序运行的基础,而后者是在所有用户线程结束时才终止的后台...
线程优先级和守护线程也是Java线程中的一部分,`Thread`类提供了设置优先级的方法,高优先级的线程更有可能获得CPU执行时间。守护线程是一种特殊的线程,它不会阻止JVM的退出,除非所有的非守护线程都已结束。 书中...
创建Java线程有两种方式:继承`Thread`类并重写`run()`方法,或者实现`Runnable`接口并提供`run()`方法。当线程对象被创建并调用`start()`方法后,线程进入可运行态,由Java的线程调度器决定何时执行`run()`方法。 ...
2. **线程创建**:Java提供两种方式创建线程,一是直接继承Thread类并重写run()方法,二是实现Runnable接口并定义run()方法,然后通过Thread类的构造函数将Runnable对象传递进去。 3. **线程交互**:线程之间的通信...
Java线程是Java编程语言中的一个核心概念,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,线程是通过类`Thread`或实现`Runnable`接口来创建和管理的。Java线程模型是基于操作系统的原生...
JAVA线程dump的分析 JAVA线程dump是指在JAVA程序中,当前线程的状态和调用堆栈的快照,能够帮助开发者了解当前程序的执行情况,诊断问题和性能瓶颈。生成JAVA线程dump的方法在不同的操作系统下是不同的,在Windows...
Java线程是多任务编程的重要概念,特别是在大型的、复杂的软件系统中,它允许程序同时执行多个不同的任务,提升程序的并发性和效率。本示例"简单的Java线程demo"旨在帮助初学者理解如何在Java中创建和管理线程。 在...
在Java出现以前,似乎人人都在谈论线程,却很少有人使用它。用线程编程是技巧性很强的且不可移植。 而在Java中却完全不同。Java的线程工具易于使用,并且像Java中的其他东西一样可以在不同的平台之间移植。这是一件...
随着Java版本的更新,Java也引入了新的并发工具类,例如java.util.concurrent包下的并发集合、原子操作类以及各种并发控制类,这些工具类提供了比传统synchronized和volatile关键字更强大、更灵活的线程同步控制机制...
#### 二、Java线程API 1. **线程控制方法** - `Thread.sleep(long millis)`: 让当前正在执行的线程暂停执行指定时间,让出CPU给其他线程使用。 - `Thread.yield()`: 提示当前线程让出CPU时间片,但不一定立即生效...