A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© 15670379287 中级黑马   /  2016-4-8 21:51  /  543 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在讲同步工具类之前,笔者想先介绍一下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();  
  •         }  
  •     }  
  • }  



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马