多线程并发库高级应用 之 java5中的线程并发库--线程池、Callable&Future

来源:互联网 发布:旅游网络销售范围 编辑:程序博客网 时间:2024/05/16 04:40

笔记摘要:

               这里首先介绍了java5中的并发的小工具包:automatic,然后介绍了线程池的概念,对使用java5的方式创建不同形式的线程进行了演示,

              之后介绍了两个 对象:Callable和Future,用于获取线程执行后的结果,对于线程锁技术则在另外一篇文章中介绍。


Java5中的线程并发库都在java.util.concurrent包及子包



一、java.util.concurrent.atomic

                           类的小工具包,支持在单个变量上解除锁的线程安全编程


1如果同一个变量要被多个线程访问,则可以使用该包中的类:

      AtomicBooleanAtomicIntegerAtomicLong 和 AtomicReference 

2AtomicIntegerArray:操作数组里面的某个整数

3同样该包中提供了可以用于反射操作的类:

      AtomicReferenceFieldUpdater、AtomicIntegerFieldUpdater 和 AtomicLongFieldUpdater 

      它们可以提供对关联字段类型的访问。



二、线程池:

       在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,

       再把任务交给内部某个空闲的线程,这就是封装。


记住:任务是提交给整个线程池,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。


示例:

   创建固定大小的线程池、创建缓存线程池 、 用线程池创建定时器

   创建单一线程池(始终保证线程池中会有一个线程在。当某线程死去,会找继任者)


注意:

  定时器中总是相对时间,我们要想指定具体时间的方法:比如明天早上10点钟执行,则可以使用明天早上10点的时间减去

  当前的时间,得到时间间隔


[java] view plaincopy
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. import java.util.concurrent.TimeUnit;  
  4.   
  5. public class ThreadPoolTest {  
  6.     public static void main(String[] args){  
  7.           
  8.         //创建固定大小的线程池,这里只能完成3个任务  
  9.         //ExecutorService threadPool = Executors.newFixedThreadPool(3);  
  10.           
  11.         //创建缓存线程池,根据任务来自动创建线程的数量,可以完成创建的所有任务  
  12.         //ExecutorService threadPool = Executors.newCachedThreadPool();  
  13.           
  14.         //创建单一线程池(始终保持线程池中有一个线程存活。当唯一线程死去,会创建新的继任者、  
  15.         ExecutorService threadPool = Executors.newSingleThreadExecutor();  
  16.           
  17.         for(int i=1;i<=10;i++){  
  18.   //内部类不能访问外部类的局部变量,所以i要定义为final,又由于i++.  
  19.   //所以在循环内部定义一个变量接收i  
  20.             final int task = i;  
  21.         threadPool.execute(new Runnable() {  
  22.               
  23.             @Override  
  24.             public void run() {  
  25.                 for(int j=1;j<=10;j++){  
  26.                     System.out.println(Thread.currentThread().getName()  
  27.                             +" is looping of "+ j+"  for task of " +task);  
  28.                 }  
  29.                   
  30.             }  
  31.         });  
  32.         }  
  33.         //验证10个任务都提交给了线程池  
  34.         System.out.println("all of 10 tasks have committed! ");  
  35.         //threadPool.shutdown();        //等任务完成后,杀死线程、  
  36.         //threadPool.shutdownNow();     //立即停止线程  
  37.       
  38.         //用线程池启动定时器  
  39.           
  40.         Executors.newScheduledThreadPool(3).schedule(  
  41.                 new Runnable() {  //任务  
  42.                 @Override  
  43.                 public void run() {  
  44.                     System.out.println("bombing!");  
  45.                 }  
  46.             },   
  47.                     5,  //5秒以后执行  
  48.                     TimeUnit.SECONDS);  //单位  
  49.               
  50.     //在某个时间执行一次后,再指定后续的执行间隔时间  
  51.         Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable(){  
  52.   
  53.             @Override  
  54.             public void run() {           
  55.                 System.out.println("bombing!");  
  56.             }  
  57.               
  58.         }, 10,   //第一次在10秒时爆炸  
  59.             3,          //以后每隔3秒爆炸一次。  
  60.         TimeUnit.SECONDS);   
  61.       
  62.     }  
  63. }  


三、Callable & Future:用于获取线程执行完的结果


       1、Callable 接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,

         并且无法抛出经过检查的异常,而Callable返回结果并且可能抛出异常的任务。

      

       2、Future 接口表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能

        使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。

     

      3Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的。

          Callable要采用ExecutorServicesubmit方法提交,返回的future对象可以取消任务、


      4CompletionService用于提交一组Callable任务,其take方法返回已完成的一个Callable任务对应的Future对象。


示例:

     这里数据的获取好比同时种了号几块地的麦子,然后等待收割,秋收时,哪块先熟,先收割哪块。

[java] view plaincopy
  1. import java.util.Random;  
  2. import java.util.concurrent.Callable;  
  3. import java.util.concurrent.CompletionService;  
  4. import java.util.concurrent.ExecutionException;  
  5. import java.util.concurrent.ExecutorCompletionService;  
  6. import java.util.concurrent.ExecutorService;  
  7. import java.util.concurrent.Executors;  
  8. import java.util.concurrent.Future;  
  9. import java.util.concurrent.TimeUnit;  
  10. import java.util.concurrent.TimeoutException;  
  11.   
  12. public class CallableAndFuture {  
  13.     public static void main(String[] args){  
  14.   
  15.   //创建一个单独的线程         
  16.   ExecutorService threadPool = Executors.newSingleThreadExecutor();  
  17.   //future泛型与Callable的类型一致        
  18.   Future<String> future = threadPool.submit(new Callable<String>(){  
  19.   
  20.             @Override  
  21.             public String call() throws Exception {  
  22.                 Thread.sleep(3000);  
  23.                 return "hello";  
  24.             }  
  25.               
  26.         });  
  27.         System.out.println("等待結果……");  
  28.           
  29.         //在指定时timeout内等待,未等到抛出TimeoutException  
  30.         //System.out.println("拿到结果:" + future.get(long timeout,TimeUnit unit));  
  31.           
  32.         try {  
  33.             System.out.println("拿到结果:" + future.get()); //获取线程执行后的结果  
  34.               
  35.         } catch (InterruptedException e) {  
  36.             // TODO Auto-generated catch block  
  37.             e.printStackTrace();  
  38.         } catch (ExecutionException e) {  
  39.             // TODO Auto-generated catch block  
  40.             e.printStackTrace();  
  41.         }  
  42.                    
  43.         //CompletionService用于提交一组Callable任务,  
  44.         //其take方法返回已完成的一个Callable任务对应的Future对象。  
  45.         ExecutorService threadPool2 = Executors.newFixedThreadPool(10);  
  46.         CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);  
  47.           
  48.               //创建10任务  
  49.         for(int i=1;i<=10;i++){  
  50.             final int seq = i;  
  51.   
  52.               //将任务提交给线程池  
  53.             completionService.submit(new Callable<Integer>(){  
  54.                 @Override  
  55.                 public Integer call() throws Exception {  
  56.                     Thread.sleep(new Random().nextInt(5000));  
  57.                     return seq;               
  58.                 }  
  59.             });  
  60.         }  
  61.         //获取结果,哪个结果先返回就先获得  
  62.         for(int i=0;i<10;i++){  
  63.             try {  
  64.                 System.out.println(completionService.take().get());  
  65.             } catch (InterruptedException e) {  
  66.                 e.printStackTrace();  
  67.             } catch (ExecutionException e) {  
  68.                 e.printStackTrace();  
  69.             }  
  70.         }  
  71.     }  
  72. }  
0 0
原创粉丝点击