隨筆-3  評論-0  文章-0  trackbacks-0
            2010年12月7日
               摘要: class文件之常量池分析 當(dāng)JVM運(yùn)行Java程序的時候,它會加載對應(yīng)的class文件,并提取class文件中的信息存放在JVM開辟出來的方法區(qū) 內(nèi)存中。那么這個class文件里面到底有些什么內(nèi)容呢?   一、class文件內(nèi)容概述   class文件是由8bits的字節(jié)流組成,全部字節(jié)構(gòu)成了15個有意義的項(xiàng)目。這些項(xiàng)目之間沒有任何無意義的字節(jié),因...  閱讀全文
          posted @ 2010-12-07 17:51 QZZF 閱讀(241) | 評論 (0)編輯 收藏
            2010年7月15日
          volatile:具有 synchronized 的可見性特性,但是不具備原子特性.這就是說線程能 夠自動發(fā)現(xiàn) volatile 變量的最新值.

          使用volatile原則:

            對變量的寫操作不依賴于當(dāng)前值。

            該變量沒有包含在具有其他變量的不變式中


          package
           zhang.feng.concurrent.atomic;

          public class VolatileTest {
              
              
          private String str="";
              
              
          public String getStr() {
                  
          return str;
              }
              
          public void setStr(String str) {
                  
          this.str = str;
              }
              
          private void doit(){
                  
                  
          new Thread(new Runnable(){
                      
          public void run() {
                          setStr(
          "沒有寫入主存中");
                          System.out.println(
          "====");
                      }
                  },
          "THREAD_ONE").start();
                  
          new Thread(new Runnable(){
                      
          public void run() {
                          String str
          =getStr();
                          System.out.println(str);
                      }
                  },
          "THREAD_TWO").start();
              }
              
              
          public static void main(String[] args){
                  VolatileTest vt
          =new VolatileTest();
                  vt.doit();
              }
          }

          上面的例子,如果不使用volatile變量,可能出現(xiàn)的情況是(出現(xiàn)幾率很小),THREAD_ONE線程在setStr()后,
          THREAD_TWO執(zhí)行了getStr(),但是由于并沒有將數(shù)據(jù)寫入主存中,而此時getStr()獲得的數(shù)據(jù)將是過時數(shù)據(jù).

          解決的方式,通過lock(開銷比較大),使用volatile變量(如上).




          正確使用 volatile 的模式
          1.狀態(tài)標(biāo)志
          volatile boolean shutdownRequested;



          public void shutdown() { shutdownRequested = true; }

          public void doWork() { 
              
          while (!shutdownRequested) { 
                  
          // do stuff
              }
          }
          可能在另一個線程中調(diào)用shutdown(),那么使用volatile可以保證shutdownRequested可見性,所以不需要使用lock來實(shí)現(xiàn)數(shù)據(jù)同步.
          該模式特征:只有一種狀態(tài)的轉(zhuǎn)換.

          2.
          一次性安全發(fā)布
          public class BackgroundFloobleLoader {
              
          public volatile Flooble theFlooble;

              
          public void initInBackground() {
                  
          // do lots of stuff
                  theFlooble = new Flooble();  // this is the only write to theFlooble
              }
          }

          public class SomeOtherClass {
              
          public void doWork() {
                  
          while (true) { 
                      
          // do some stuff
                      
          // use the Flooble, but only if it is ready
                      if (floobleLoader.theFlooble != null
                          doSomething(floobleLoader.theFlooble);
                  }
              }
          }
          在如果initInBackground(寫入)和doWork(讀取)在不同線程同時執(zhí)行時,那么可能獲得的更新后的Flooble對象也可能是未更新前的,而是用volatile可以保證是讀取到更新后的對象.

          該模式的一個必要條件是:被發(fā)布的對象必須是線程安全的,或者是有效的不可變對象(有效不可變意味著對象的狀態(tài)在發(fā)布之后永遠(yuǎn)不會被修改)。



          3.
          獨(dú)立觀察
          public class UserManager {
              
          public volatile String lastUser;

              
          public boolean authenticate(String user, String password) {
                  
          boolean valid = passwordIsValid(user, password);
                  
          if (valid) {
                      User u 
          = new User();
                      activeUsers.add(u);
                      lastUser 
          = user;
                  }
                  
          return valid;
              }
          }

          該模式可以用于收集最近一次登錄信息,并提交其他應(yīng)用處理.

          4.“volatile bean” 模式
          @ThreadSafe
          public class Person {
              
          private volatile String firstName;
              
          private volatile String lastName;
              
          private volatile int age;

              
          public String getFirstName() { return firstName; }
              
          public String getLastName() { return lastName; }
              
          public int getAge() { return age; }

              
          public void setFirstName(String firstName) { 
                  
          this.firstName = firstName;
              }

              
          public void setLastName(String lastName) { 
                  
          this.lastName = lastName;
              }

              
          public void setAge(int age) { 
                  
          this.age = age;
              }
          }

          結(jié)束語
          與鎖相比,Volatile 變量是一種非常簡單但同時又非常脆弱的同步機(jī)制,它在某些情況下將提供優(yōu)于鎖的性能和伸縮性。如果嚴(yán)格遵循 volatile 的使用條件 —— 即變量真正獨(dú)立于其他變量和自己以前的值 —— 在某些情況下可以使用 volatile 代替 synchronized 來簡化代碼。然而,使用 volatile 的代碼往往比使用鎖的代碼更加容易出錯。本文介紹的模式涵蓋了可以使用 volatile 代替 synchronized 的最常見的一些用例。遵循這些模式(注意使用時不要超過各自的限制)可以幫助您安全地實(shí)現(xiàn)大多數(shù)用例,使用 volatile 變量獲得更佳性能。
          posted @ 2010-07-15 16:02 QZZF| 編輯 收藏
            2010年7月14日
          使用CountDownLatch可以保證指定線程數(shù)的順利完成,如下:

          public
           class CountDownLatchTest {
              
          static int N=5;//指定需要等待完成的線程數(shù)
              
              
          static CountDownLatch cdl=new CountDownLatch(N);
              
              
          static List list=new ArrayList();
              
              
          public static void main(String[] args) {
                  for(int i=0;i<N;i++){
                      
          new Thread(new countDownLatchRunnable(i),"Thread_"+i).start();
                  }
                  
          try {
                      cdl.await();
          //等待在cdl.countDown()之前進(jìn)行的操作都順利完成
                  } catch (InterruptedException e) {
                      
          // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
                  System.out.println(
          "LIST_1 size["+list.size()+"]");//希望獲得是size>=5
              }
              
              
          static class countDownLatchRunnable implements Runnable{
                  
          int num;
                  
                  countDownLatchRunnable(
          int num){
                      
          this.num=num;
                  }
                  
                  @Override
                  
          public void run() {
                      doWork();
          //而在cdl.countDown()之前的操作,則在調(diào)用await()時,則會等待該部分操作完成
                      cdl.countDown();
                      list.add(num);
          //如果在cdl.countDown()后添加操作,那么在cdl.await()處并不會等待該部分操作完成,而是會有競爭
                  }
                  
          private void doWork(){
                      
          //執(zhí)行其他工作
                      list.add(num);
                  }
              }
          }

          如果不使用
          CountDownLatch,那么在main線程和其他線程都是處于競爭關(guān)系,最后的size結(jié)果可能也是隨機(jī)存在的


          posted @ 2010-07-14 16:04 QZZF| 編輯 收藏
          僅列出標(biāo)題  
          主站蜘蛛池模板: 景德镇市| 建水县| 红河县| 阿坝县| 海兴县| 土默特左旗| 文昌市| 革吉县| 富锦市| 汪清县| 星子县| 永丰县| 宁河县| 扬中市| 民乐县| 新泰市| 利川市| 桃园县| 陆河县| 阳城县| 长岛县| 屏山县| 汤原县| 宁河县| 河曲县| 陵川县| 五台县| 宜君县| 乌拉特后旗| 濮阳市| 凤凰县| 辽阳市| 沈阳市| 十堰市| 左贡县| 绍兴市| 孙吴县| 东光县| 石台县| 蕉岭县| 申扎县|