JDK5.0关于多线程的新特性
概述
1:三个新加的多线程包
2:Callable 和 Future 接口
3:新的线程执行架构
4:Lockers 和Condition 接口
5: Synchronizer:同步装置
6: BlockingQueue 接口
7:Atomics 原子级变量
8:Concurrent Collections 共点聚集
1:三个新加的多线程包
java.util.concurrent,
包含了常用的多线程工具,是新的多线程工具的主体。
java.util.concurrent.atomic,
包含了不用加锁情况下就能改变值的原子变量
比如说AtomicInteger 提供了addAndGet()方法
java.util.concurrent.locks
包含锁定的工具。
2:Callable 和 Future 接口
Callable 和Runnable 有几点不同:
Callable 规定的方法是call(),而Runnable 规定的方法是run().
Callable 的任务执行后可返回值,而Runnable 的任务是不能返回值的。
call()方法可抛出异常,而run()方法是不能抛出异常的。
运行 Callable 任务可拿到一个Future 对象,通过Future 对象可了解任务
执行情况,可取消任务的执行,还可获取任务执行的结果。
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Executor { public static void main(String[] args){ //*1 DoCallStuff call1 = new DoCallStuff(0); DoCallStuff call2 = new DoCallStuff(1); DoCallStuff call3 = new DoCallStuff(2); //*2 ExecutorService es = Executors.newFixedThreadPool(3); //*3 Future<String> future1 = es.submit(call1); Future<String> future2 = es.submit(call2); Future<String> future3 = es.submit(call3); try { //*4 System.out.println(future1.get()); //*5 Thread.sleep(3000); System.out.println("Thread 2 terminated? :" + future2.cancel(true)); //*6 System.out.println(future3.get()); } catch (ExecutionException ex) { ex.printStackTrace(); }
}
3:新的线程执行架构
主要由三个接口和其相应的具体类组成。
这三个接口是Executor, ExecutorService 和ScheduledExecutorService,
4:Lockers 和Condition 接口
Lockers接口
在5.0 以前,锁定的功能是由Synchronized 关键字来实现的,这样做存在几个问题:
每次只能对一个对象进行锁定。若需要锁定多个对象,编程就比较麻烦,
一不小心就会出现死锁现象。
如果线程因拿不到锁定而进入等待状况,是没有办法将其打断的
Java 5.0 里出现两种锁的工具可供使用:Lock和ReadWriteLock
Condition接口
用于处理经典的生产者、消费者问题
5: Synchronizer:同步装置
Java 5.0 里新加了4 个协调线程间进程的同步装置,
它们分别是Semaphore, CountDownLatch, CyclicBarrier 和Exchanger
Semaphore:
用来管理一个资源池的工具,Semaphore 可以看成是个通行证,线程要想从资
源池拿到资源必须先拿到通行证,Semaphore 提供的通行证数量和资源池的大
小一致。如果线程暂时拿不到通行证,线程就会被阻断进入等待状态。
CountDownLatch:
CountDownLatch 是个计数器,它有一个初始数,等待这个计数器的线程必须等
到计数器倒数到零时才可继续。比如说一个Server 启动时需要初始化4 个部件,
Server 可以同时启动4 个线程去初始化这4 个部件,然后调用
CountDownLatch(4).await()阻断进入等待,每个线程完成任务后会调用一次
CountDownLatch.countDown()来倒计数, 当4 个线程都结束时
CountDownLatch 的计数就会降低为0,此时Server 就会被唤醒继续下一步操作
CyclicBarrier:
CyclicBarrier 类似于CountDownLatch 也是个计数器,不同的是CyclicBarrier
数的是调用了CyclicBarrier.await()进入等待的线程数,当线程数达到了
CyclicBarrier 初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。
(似乎没有什么现实中的好例子)
Exchanger:
顾名思义 Exchanger 让两个线程可以互换信息。用一个例子来解释比较容易。
例子中服务生线程往空的杯子里倒水,顾客线程从装满水的杯子里喝水,然后通
过Exchanger 双方互换杯子,服务生接着往空杯子里倒水,顾客接着喝水,然
后交换,如此周而复始。
6: BlockingQueue 接口
BlockingQueue 是一种特殊的Queue,若BlockingQueue 是空的,从
BlockingQueue 取东西的操作将会被阻断进入等待状态直到BlocingkQueue 进
了新货才会被唤醒。同样,如果BlockingQueue 是满的任何试图往里存东西的
操作也会被阻断进入等待状态,直到BlockingQueue 里有新的空间才会被唤醒
继续操作
7:Atomics 原子级变量
原子量级的变量,主要的类有 AtomicBoolean, AtomicInteger,
AotmicIntegerArray, AtomicLong, AtomicLongArray, AtomicReference ……。
这些原子量级的变量主要提供两个方法:
compareAndSet(expectedValue, newValue):
比较当前的值是否等于expectedValue,若等于把当前值改成newValue,并返回true。若不等,返回false。
getAndSet(newValue):
把当前值改为newValue,并返回改变前的值。
这些原子级变量利用了现代处理器(CPU)的硬件支持可把两步操作合为一步的功能,避免了不必要的锁定,提高了程序的运行效率。
8:Concurrent Collections 共点聚集
在 Java 的聚集框架里可以调用Collections.synchronizeCollection(aCollection)
将普通聚集改变成同步聚集,使之可用于多线程的环境下。但同步聚集在一个
时刻只允许一个线程访问它,其它想同时访问它的线程会被阻断,导致程序运行
效率不高。Java 5.0 里提供了几个共点聚集类,它们把以前需要几步才能完成的
操作合成一个原子量级的操作,这样就可让多个线程同时对聚集进行操作,避免
了锁定,从而提高了程序的运行效率。Java 5.0 目前提供的共点聚集类有:
ConcurrentHashMap, ConcurrentLinkedQueue, CopyOnWriteArrayList 和
CopyOnWriteArraySet.
来源:
http://wenku.baidu.com/view/77aff7e96294dd88d0d26b7b.html
浙公网安备 33010602011771号