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

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类的示意代码进行原理分析:
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:改为缓存线程池,可以看到当前有多少个任务,就会分配多少个线程为之服务。
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:
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());
      }
     
 }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值