黑马程序员技术交流社区
标题:
JAVA多线程-同步工具类
[打印本页]
作者:
15670379287
时间:
2016-4-8 21:51
标题:
JAVA多线程-同步工具类
在讲同步工具类之前,笔者想先介绍一下Runnable,Callable,Future,Executor,FutureTask这几个类或接口。
1 Runnable和Callable是接口,实现两者的任何一个可以开发多线程。但是前者无法返回线程的执行结果,后者可以返回线程的执行结果。
2 Future是一个接口,用于等待或者查看Callable线程的返回结果。
3 Executor是线程的调度容器。
4 FutureTask是一个类,他实现了Runnable接口和Future接口。可以以一个实现了runnable接口的类或者是实现了callable接口的类为参数进行构造。具有Runnable和Future的双重优点。
下面举一个例子(future和callable结合,获得返回结果):
Java代码
[url=]
[/url]
import java.util.concurrent.*;
public class Demo{
public static void main(String [] args){
ExecutorService executor=Executors.newCachedThreadPool();
Task task=new Task();
Future<Integer> result=executor.submit(task);
executor.shutdown();
System.out.println("main thread is running");
try{
System.out.println("task result="+result.get());
}catch(Exception e){
e.printStackTrace();
}
System.out.println("over");
}
}
class Task implements Callable<Integer>{
public Integer call() throws Exception{
System.out.println("sub thread is running");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<101;i++)
sum += i;
return sum;
}
}
上面的例子使用FutureTask来写:
Java代码
[url=]
[/url]
import java.util.concurrent.*;
public class Demo{
public static void main(String [] args){
ExecutorService executor=Executors.newCachedThreadPool();
FutureTask<Integer> futureTask=new FutureTask<Integer>(new Task());
executor.submit(futureTask);
executor.shutdown();
System.out.println("main thread is running");
try{
System.out.println("task result="+futureTask.get());
}catch(Exception e){
e.printStackTrace();
}
System.out.println("over");
}
}
class Task implements Callable<Integer>{
public Integer call() throws Exception{
System.out.println("sub thread is running");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<101;i++)
sum += i;
return sum;
}
}
相信读者可以看到上面两个例子的区别,future本身不是一个线程,他只能用来等待或获取callable线程的返回结果;而futureTask本身就是一个线程,而且他能够返回结果。
FutureTask做为一个同步工具类,有着广泛的应用。下面我们来看几个其他的同步工具类:Latch-闭锁(我觉得叫门闩更好理解),Semophore-信号量,Carrier-栅栏。
1 闭锁:在多线程执行过程中设置几个门闩,只有当所有的门闩被打开时,被挡在门外的线程才能继续执行。
2 信号量:控制同时访问某个资源或者进行某种操作的线程数量。
3 栅栏:用于阻塞多个相关的线程,一直到某个事件发生。
闭锁例子:
Java代码
[url=]
[/url]
import java.util.concurrent.*;
class Util{
public static long testTime(int nThreads,final Runnable task) throws InterruptedException {
//为启动门设置一个门闩,当门闩被打开时,放行所有被挡在门外的线程
final CountDownLatch startGate=new CountDownLatch(1);
//为结束门设置n个门闩,当n个门闩被打开时,放行所有被挡在门外的线程
final CountDownLatch endGate=new CountDownLatch(nThreads);
//测试n个线程并发执行任务task的时间
for(int i=0;i<nThreads;i++){
Thread t=new Thread(){
public void run(){
try {
startGate.await();
try{
task.run();
}catch(Exception e){
endGate.countDown();
}
} catch (InterruptedException e) {}
}
};
t.start();
}
//循环中的内容使得有n个线程在startGate门外等着执行task任务
long start=System.nanoTime();
startGate.countDown();//打开startGate上的门闩
endGate.await();//等待endGate门开
long end =System.nanoTime();
return end-start;
}
}
pub
栅栏例子:
Java代码
[url=]
[/url]
import java.util.concurrent.*;
public class Demo{
public static void main(String [] args) throws InterruptedException {
final CyclicBarrier cyclicBarrier=new CyclicBarrier(10, new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("10 个人都到达会议室,开会");
}
});
for(int i=0;i<10;i++){
final long tmp=i;
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000*(11-tmp));
System.out.println("person"+tmp+" come here");
try {
cyclicBarrier.await();//等待其他线程到达
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {}
}
});
thread.start();
}
}
}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2