线程并发 共享数据及线程并发

ThreadLocal
 
关于线程范围内的变量共享的举例:监狱里罪犯的排队打饭,针对A罪犯,那几个打饭和打菜和打汤的模块操作的饭盆是A罪犯相关的饭盆;针对B罪犯,那几个打饭和打菜和打汤的模块操作的饭盆是B罪犯相关的饭盆。
首先用如下代码来说明如何实现全局共享:
Class GlobalData
{
     public static ThreadLocal var = new ThreadLocal();
}
全局静态变量可以被多个模块类共享,并且不管是哪个线程来调用,数据都是同一份。
 
接着用如下代码来说全局共享的变量被不同线程调用时,希望有不同的返回值的情况。
Class A{
public void say(){
GlobalData.var.get()
}
}
 
线程1、线程2 、线程3访问的GlobalData.var得到的对象是否是同一个?要反复强调这是同一个对象。但是,使用的GlobalData.var.get()得到数据是肯定同一个吗?那就不一定了!例如这里要讲的Threadlocal就可以为三个线程分别返回三个不同的值。
三个线程用如下代码来set这个GlobalData.var对象的值时
GlobalData.var.set(new Random().nextInt(10000));
最终存进去了几个值?这时候要为每个线程各自分别存储进去一个值,即总共存储进了三个值。
------------------------------
通过ThreadLocal类的示意代码进行原理分析:
[java] view plaincopyprint?
  1. ThreadLocal 
  2. HashMap hashMap = new HashMap(); 
  3.         void set(Object obj) 
  4. hashMap.put(Thread.currentThread(),obj); 
  5. object get() 
  6. return hashMap.get(Thread.currentThread()); 
ThreadLocal
{
HashMap hashMap = new HashMap();
        void set(Object obj)
{
hashMap.put(Thread.currentThread(),obj);
}
object get()
{
return hashMap.get(Thread.currentThread());
}
}
 
 
java5中线程并发库  java.util.concurrent
 
Volatile的意思是说:在jvm中,一个线程更新了共享变量i,另外一个线程立即去读取共享区中的i时,读到的可能不是刚才另外那个线程更新过的结果,这就类似数据库中的事务隔离级别中的read uncommited,volatile就是解决这个问题的。
 
关于线程池的讲解:
 
在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,这就是封装。记住,任务是提交给整个线程池
步骤1:用3个大小的固定线程池去执行10个内部循环10次就结束的任务,为了观察固定线程池下的其他任务一直再等待,希望打印出正在执行的线程名、任务序号和任务内部的循环次数,刚开始看到只有3个线程在执行,并看到任务前仆后继的效果。注意:这10个任务要用各自独立的runnable对象,才能看到任务的序号。
步骤2:改为缓存线程池,可以看到当前有多少个任务,就会分配多少个线程为之服务。
 
[java] view plaincopyprint?
  1. package cn.itcast.foundationsummary; 
  2. import java.util.concurrent.ExecutorService; 
  3. import java.util.concurrent.Executors; 
  4. import java.util.concurrent.ScheduledExecutorService; 
  5. import java.util.concurrent.TimeUnit; 
  6. publicclass ThreadPoolTest { 
  7. publicstaticvoid main(String[] args) { 
  8. //ExecutorService service = Executors.newFixedThreadPool(3);  
  9. ExecutorService service = Executors.newCachedThreadPool(); 
  10. for(int i=1;i<=10;i++){ 
  11. finalint sequence = i; 
  12. //仔细品味runnable对象放到循环里面和外面的区别,为了让每个对象有自己独立的编号   
  13. service.execute(new Runnable(){ 
  14. publicvoid run() { 
  15. try{Thread.sleep(200);}catch(Exception e){} 
  16. for(int j=1;j<=5;j++){ 
  17.   System.out.println(Thread.currentThread().getName() + "is serving "  
  18. + sequence + " task:" + "loop of " + j); 
  19. }); 
  20. /*
  21. 用下面这句代码来说明上面的代码是在提交任务,并且所有的任务都已经提交了,但任务是什么时候执行的,则是由线程池调度的!
  22. */ 
  23. System.out.println(“all task have committed!”);  
  24. //注意与service.shutdownNow()的区别。  
  25. service.shutdown(); 
  26. ScheduledExecutorService scheduledService = Executors.newScheduledThreadPool(1);//定时器  
  27. scheduledService.scheduleAtFixedRate( 
  28. new Runnable(){ 
  29. publicvoid run() { 
  30. System.out.println("bomb!!!"); 
  31. }},  
  32. 5,  
  33. 1
  34. TimeUnit.SECONDS); 
package cn.itcast.foundationsummary;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
public static void main(String[] args) {
//ExecutorService service = Executors.newFixedThreadPool(3);
ExecutorService service = Executors.newCachedThreadPool();
for(int i=1;i<=10;i++){
final int sequence = i;
//仔细品味runnable对象放到循环里面和外面的区别,为了让每个对象有自己独立的编号 
service.execute(new Runnable(){
public void run() {
try{Thread.sleep(200);}catch(Exception e){}
for(int j=1;j<=5;j++){
  System.out.println(Thread.currentThread().getName() + "is serving " 
+ sequence + " task:" + "loop of " + j);
}
}
});
}
/*
用下面这句代码来说明上面的代码是在提交任务,并且所有的任务都已经提交了,但任务是什么时候执行的,则是由线程池调度的!
*/
System.out.println(“all task have committed!”); 
//注意与service.shutdownNow()的区别。
service.shutdown();
ScheduledExecutorService scheduledService = Executors.newScheduledThreadPool(1);//定时器
scheduledService.scheduleAtFixedRate(
new Runnable(){
public void run() {
System.out.println("bomb!!!");
}}, 
5, 
1,
TimeUnit.SECONDS);
}
}
,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。
 
 
启动定时器方式:
1. submit()
2. execute();
3.schedule();
 
取得绝对值,比如定义在今年年底发生的事件
 
date.getTime() - System.currentTimeMills();// 用想要的时间减去当前系统时间来定义需要延迟的时间
 
shutdown与shutdownNow的比较
 
shutdown  如果仍在为别的程序服务,则需要等待服务完成后停止
shutdownNow 无论线程是否为别的程序服务,立刻停止线程
 
 
Callable and Future
 
提交任务的时候有返回值,而且需要拿到该返回值:
 
eg:
 
[java] view plaincopyprint?
  1. package cn.itcast.thread; 
  2.  
  3.  
  4. import java.util.concurrent.Callable; 
  5. import java.util.concurrent.CompletionService; 
  6. import java.util.concurrent.ExecutorCompletionService; 
  7. import java.util.concurrent.ExecutorService; 
  8. import java.util.concurrent.Executors; 
  9. import java.util.concurrent.Future; 
  10.  
  11.  
  12. publicclass CallableAndFuture { 
  13.  
  14. /**
  15.   * @param args
  16.   */ 
  17. publicstaticvoid main(String[] args) throws Exception{ 
  18.     //提交一个任务,有返回值   
  19.        ExecutorService service =  Executors.newSingleThreadExecutor(); 
  20.         
  21.        Future<String> future = service.submit(new Callable<String>(){ 
  22.  
  23.   @Override 
  24.   public String call() throws Exception { 
  25.     
  26.    try
  27.     Thread.sleep(1000); 
  28.    }catch(Exception e){ 
  29.     e.printStackTrace(); 
  30.    } 
  31.    return"www.itcast.cn"
  32.   } 
  33.  
  34.        }); 
  35.        System.out.println("task has been committed"); 
  36.        System.out.println(future.get()); 
  37.         
  38.        //提交多个任务  
  39.       CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(service); 
  40.       for(int i = 0 ;i <10;i++ ){ 
  41.        final Integer sequence = i+1
  42.        completionService.submit(new Callable<Integer>(){ 
  43.                 
  44.        @Override 
  45.        public Integer call() throws Exception { 
  46.          
  47.         try{Thread.sleep((long) (Math.random()*1000));//随机数让每次任务执行间隔时间不同  
  48.         }catch(Exception e){ 
  49.          e.printStackTrace(); 
  50.         } 
  51.                      
  52.         return sequence; 
  53.        } 
  54.              
  55.            }); 
  56.       } 
  57.        
  58.       for(int i =0 ;i<10;i++){ 
  59.        Future<Integer> f = completionService.take(); 
  60.        System.out.println(f.get()); 
  61.       } 
  62.       
  63.  
package cn.itcast.thread;


import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class CallableAndFuture {

 /**
  * @param args
  */
 public static void main(String[] args) throws Exception{
    //提交一个任务,有返回值 
       ExecutorService service =  Executors.newSingleThreadExecutor();
       
       Future<String> future = service.submit(new Callable<String>(){

  @Override
  public String call() throws Exception {
   
   try{
    Thread.sleep(1000);
   }catch(Exception e){
    e.printStackTrace();
   }
   return "www.itcast.cn";
  }

       });
       System.out.println("task has been committed");
       System.out.println(future.get());
       
       //提交多个任务
      CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(service);
      for(int i = 0 ;i <10;i++ ){
       final Integer sequence = i+1;
       completionService.submit(new Callable<Integer>(){
               
       @Override
       public Integer call() throws Exception {
        
        try{Thread.sleep((long) (Math.random()*1000));//随机数让每次任务执行间隔时间不同
        }catch(Exception e){
         e.printStackTrace();
        }
                    
        return sequence;
       }
            
           });
      }
      
      for(int i =0 ;i<10;i++){
       Future<Integer> f = completionService.take();
       System.out.println(f.get());
      }
     
 }

}

 

posted @ 2012-11-08 11:57  温诗袀  阅读(186)  评论(0编辑  收藏  举报