在路上

          路上有驚慌,路上有理想

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            28 Posts :: 1 Stories :: 10 Comments :: 0 Trackbacks

          2010年11月11日 #

          1.linux安裝字體
             以微軟雅黑為例,找到msyh.ttf ,copy至下面的文件夾
             usr/share/fonts/msyh
            執(zhí)行命令:fc-cache -fv
            重啟jvm即可
          2.drawString 部分代碼
          private static BufferedImage drawString(int type, boolean isWhite,
                      int width, int height, String price, Font font_money, Font font,
                      Graphics2D g2d, Rectangle2D bounds, Rectangle2D bounds_money) {
                   BufferedImage image;
                   //透明背景
                    image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);  
                   g2d.dispose();  
                   g2d = image.createGraphics();  
                   //反鋸齒字體
                   g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                   if(!isWhite){
                       //非白字
                       g2d.setColor(new Color(236,0,137));  
                   }else{
                       //白字
                       g2d.setColor(new Color(255,255,255));  
                   }
                   //字體居中
                   double y = (height - bounds.getHeight()) / 2;      
                   double ascent = -bounds.getY();      
                   double baseY = y + ascent;      

                   g2d.setStroke(new BasicStroke(1));  
                   g2d.setFont(font_money);
                   g2d.drawString(FONT_RMB_CHAR, -2, (int)baseY);  
                   g2d.setFont(font);
                   g2d.drawString(price, (int)bounds_money.getWidth()-4, (int)baseY);
                   g2d.dispose();
                   return image;
              }
          3.如果需要根據(jù)字符串的長度生成圖片的寬度,可以使用如下方法
           Rectangle2D bounds = font.getStringBounds(price, context);
           width = (int)(bounds.getWidth();

          4.批量生成,使用java自帶的線程池,并使用CompletionService,目的是在線程處理結(jié)束后得到生成成功的ProductId
                public boolean generateImagesBatch(){
                    boolean flag=true;
                    ExecutorService exec = Executors.newFixedThreadPool(8);
                     CompletionService<CallBack> completionService=
                              new ExecutorCompletionService<CallBack>(exec);
                    long startTime=System.currentTimeMillis();
                        String sql="select productId,price from prod";
                      List<Map> skuList = this.cmsJdbcTemplate.queryForList(sql);
                      for(Map map:skuList){
                          String prodId=((BigDecimal)map.get("productId")).toString();
                          double price=((BigDecimal)map.get("price")).doubleValue();
                          completionService.submit(new CreateImageConcurrent(prodId,price,FontEnum.ONE,false));               
                          completionService.submit(new CreateImageConcurrent(prodId,price,FontEnum.TWO,false));            }
                      long endTime=System.currentTimeMillis()-startTime;
                      log.info("query db time>>>>>>>>>>>>>>"+endTime/1000);
                      
                      Future<CallBack> future;
                      int count=skuList.size()*6;
                      log.info("generateImagesBatch count:"+count);
                      try {
                          while(count>0){
                              future = completionService.take();
                              CallBack callBack = future.get();
                              if(null!=callBack){
                                  count--; log.info("generateImagesBatch prod id:"+callBack.getSuccesMessage());                    }
                          }
                      endTime=System.currentTimeMillis()-startTime;
                      log.info("create images time>>>>>>>>>>>>>>"+endTime/1000);
                      log.info("generateImagesBatch success!");
                      flag=true;
                      } catch (ExecutionException e) {
                          flag=false;
                          log.error("generateImagesBatch fail::ExecutionException::"+e.getMessage());
                      } catch (InterruptedException e) {
                          flag=false;
                          log.error("generateImagesBatch fail::InterruptedException::"+e.getMessage());
                      }finally{
                          exec.shutdown();
                      }
                      return flag;
                }
          posted @ 2012-04-18 11:35 阮步兵 閱讀(1867) | 評(píng)論 (0)編輯 收藏

          以下只是一些概念


          1.SemaphoreCountDownLatch
           
          Semaphore 可用于控制特定資源請(qǐng)求(線程/操作)數(shù)量
           
          CountDownLatch 在功能上類似于Semaphore。區(qū)別是,Semaphore允許一次一個(gè)線程的話,CountDownLatch可以允許多個(gè)線程在特定的時(shí)間一起執(zhí)行。

          2.CAS操作
            根據(jù)英文直譯其實(shí)可以理解其含義,compare and set.

            CAS 操作包含三個(gè)操作數(shù) —— 內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會(huì)自動(dòng)將該位置值更新為新值。否則,處理器不做任何操作。CAS 認(rèn)為位置 V 應(yīng)該包含值 A;如果包含該值,則將 B 放到這個(gè)位置;否則,不要更改該位置,只告訴我這個(gè)位置現(xiàn)在的值即可通常將 CAS 用于同步的方式是從地址 V 讀取值 A,執(zhí)行多步計(jì)算來獲得新值 B,然后使用 CAS 將 V 的值從 A 改為 B。如果 V 處的值尚未同時(shí)更改,則 CAS 操作成功。

          3.ABA問題

            因?yàn)樵诟?V 之前,CAS 主要詢問“V 的值是否仍為 A”,所以在第一次讀取 V 以及對(duì) V 執(zhí)行 CAS 操作之前,如果將值從 A 改為 B,然后再改回 A,會(huì)使基于 CAS 的算法混亂。在這種情況下,CAS 操作會(huì)成功,但是在一些情況下,結(jié)果可能不是您所預(yù)期的。這類問題稱為 ABA 問題

          4.原子操作

             A與B兩個(gè)操作。從執(zhí)行A的線程看,當(dāng)其他線程執(zhí)行B時(shí),要么B全部執(zhí)行完成,要么一點(diǎn)都不執(zhí)行。這樣A與B互為原子操作。要保證數(shù)據(jù)狀態(tài)的一致性,要在單一的原子操作中更新所有相關(guān)聯(lián)的狀態(tài)。

          5.可見性
           
             在單線程環(huán)境下,讀寫操作都在一個(gè)線程內(nèi)完成,不存在可見性問題。但是,當(dāng)讀與寫操作不在同一個(gè)線程內(nèi)時(shí),就需要有可見性的要求——即可變的共享變量對(duì)所有線程都是可見的。

          6.重排序

              JVM實(shí)現(xiàn)中,線程內(nèi)部維持順序化語義。如果程序的最終結(jié)果等同于它在嚴(yán)格的順序化環(huán)境下的結(jié)果,那么指令的執(zhí)行順序就可能與代碼的順序不一致。這個(gè)過程通過叫做指令的重排序。比如Java存儲(chǔ)模型允許編譯器重排序操作指令,在寄存器中緩存數(shù)值,還允許CPU重排序,并在處理器的緩存中緩存數(shù)值。

             當(dāng)然,在沒有同步的多線程情況下,編譯器,處理器,運(yùn)行時(shí)安排操作的執(zhí)行順序可能完全出人意料。

          7.內(nèi)部鎖

            每個(gè)Java對(duì)象都可以隱士的扮演一個(gè)用于同步的鎖的角色。比如synchronized(object){},執(zhí)行線程進(jìn)入synchronized塊 之前自動(dòng)獲得鎖。無論是正確執(zhí)行或是拋出異常,最終都會(huì)釋放該鎖。內(nèi)部鎖是一種互斥鎖(mutex)——至多只有一個(gè)線程可以擁有鎖。JDK中有該鎖的實(shí) 現(xiàn)。

          8.鎖與內(nèi)存

             鎖不僅僅是關(guān)于同步與互斥,也是關(guān)于內(nèi)存可見性的。為了保證所有線程都能訪問共享變量的最新值,讀和寫的線程必須使用公用的鎖進(jìn)行同步。

          9.鎖與volatile

             加鎖可以保證可見性與原子性,volatile只能保證可見性。

          10.happen-before法則

            Java存儲(chǔ)模型有一個(gè)happens-before原則,就是如果動(dòng)作B要看到動(dòng)作A的執(zhí)行結(jié)果(無論A/B是否在同一個(gè)線程里面執(zhí)行),那么A/B就需要滿足happens-before關(guān)系。比如一個(gè)對(duì)象構(gòu)造函數(shù)的結(jié)束happens-before與該對(duì)象的finalizer的開始


          參考:https://www.ibm.com/developerworks/cn/java/j-jtp11234/

               http://www.ibm.com/developerworks/cn/java/j-5things5.html

               http://www.aygfsteel.com/xylz/archive/2010/07/03/325168.html

              《Java 并發(fā)編程實(shí)踐》

          posted @ 2010-12-15 18:18 阮步兵 閱讀(1751) | 評(píng)論 (0)編輯 收藏

          BTrace是一個(gè)實(shí)時(shí)監(jiān)控工具,使用了java agent jvm attach技術(shù),可以在product的情況下實(shí)時(shí)監(jiān)控線上程序的運(yùn)行情況。另,有插件可與visualVM一起使用。
          不多說了,具體的可見:http://kenai.com/projects/btrace

          下面介紹幾個(gè)Helloworld示例:
          主要使用了btrace命令:btrace [pid] class

          pid可由jps命令快速查詢

          1.監(jiān)控方法輸入?yún)?shù):
           @OnMethod(
                          clazz="com.btrace.Person",
                          method="/set.*/"
                      )
                      public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
                          println(pcn);
                          println(pmn);
                          printArray(args);
                      }

          執(zhí)行btract命令
          后臺(tái)輸出:
          com.btrace.Person
          setId
          [1, ]……

          2.監(jiān)控方法返回值
            @OnMethod(
                           clazz="com.btrace.Person",
                           method="/get.*/",
                           location=@Location(Kind.RETURN)
                         )  
               public static void defineclass(@Return String cl) {
                     println(Strings.strcat("getValue ", cl));
                     Threads.jstack();
                 }
          執(zhí)行btract命令
          后臺(tái)輸出:
          getValue gum
          com.btrace.TestThread.main(TestThread.java:23)

          3.監(jiān)控jvm內(nèi)存使用情況
            @OnTimer(4000)
              public static void printMem() {
                  println("Heap:");
                  println(heapUsage());
                  println("Non-Heap:");
                  println(nonHeapUsage());
              }
          執(zhí)行btract命令
          后臺(tái)輸出:
          Heap:
          init = 268435456(262144K) used = 26175176(25561K) committed = 251658240(245760K)
           max = 492175360(480640K)
          Non-Heap:
          init = 12746752(12448K) used = 5892104(5754K) committed = 13598720(13280K) max =
           100663296(98304K)
          4.監(jiān)控方法執(zhí)行時(shí)間
             @TLS private static long startTime;
             
              @OnMethod(clazz="com.btrace.Person",method="setId")
              public static void onCall(){
                  println("enter this method");
                  startTime=timeMillis();
              }
             
              @OnMethod(clazz="com.btrace.Person",method="setId",location=@Location(Kind.RETURN))
              public static void onReturn(){
                  println("method end!");
                  println(strcat("Time taken ms",str(timeMillis()-startTime)));
              }
            后臺(tái)輸出:
             enter this method
             method end!
             Time taken ms0
          5.監(jiān)控Thread start
           @OnMethod(
                  clazz="java.lang.Thread",
                  method="start"
              )
              public static void func() {
                  println("about to start a thread!");
              }
          后臺(tái)輸出:about to start a thread!
          posted @ 2010-12-10 18:30 阮步兵 閱讀(3769) | 評(píng)論 (1)編輯 收藏

               摘要: 1.注意auto_increment mysql5.0在高并發(fā)下(每天近2億)插入單表數(shù)據(jù)出現(xiàn)了死鎖(偶現(xiàn)),查了下相關(guān)文檔,發(fā)現(xiàn)是因?yàn)椴捎昧薬uto-increment的主鍵帶來的問題,造成Table級(jí)的死鎖。 原因:對(duì)于auto_increment字段,innodb會(huì)在內(nèi)存里保存一個(gè)計(jì)數(shù)器用來記錄auto_increment的值,當(dāng)插入一個(gè)新行數(shù)據(jù)時(shí),就會(huì)用一個(gè)表鎖來鎖住這個(gè)計(jì)數(shù)器,所以會(huì)...  閱讀全文
          posted @ 2010-12-09 12:56 阮步兵 閱讀(1670) | 評(píng)論 (2)編輯 收藏

          一.限制設(shè)計(jì)——從結(jié)構(gòu)上說,是利用封裝技術(shù),保證某一時(shí)刻只有一個(gè)活動(dòng)訪問某個(gè)對(duì)象。

          方式主要三類,方法限制、線程限制和對(duì)象內(nèi)限制

          方法限制:

             1.方法內(nèi)部限制:采用局部變量方式

             2.方法間傳遞限制:

                   a.調(diào)用者copy:比如print(p) 可以改為print(new Point(p));

                   b.接收者copy:Point p=new Point(p.x,p.y);

                   c.標(biāo)量參數(shù):print(int x,int y);d.print(p.x,p.y);

          線程限制:

               1.最簡單的方法是將所有可變對(duì)象都放在一個(gè)線程內(nèi)執(zhí)行

                         public display(){

                                   new Thread(){

                                            public void run(){//do something here}

                                }.start()

                          }

                2.線程私有成員變量

                   最直接的辦法是利用現(xiàn)有類:ThreadLocal.

                  當(dāng)然你可以利用Thread.currentThread()自己實(shí)現(xiàn)一個(gè)類似功能的類,但Thread.currentThread有限制,就是對(duì)特定線程的一類。

                  而ThreadLocal則擺脫了這樣的限制。而且在線程內(nèi)對(duì)ThreadLocal私有變量的讀寫不需要同步。

          對(duì)象限制

                 在前面兩種方法都不能做到對(duì)對(duì)象的限制訪問時(shí),你就不得不使用鎖。但同時(shí),也可以對(duì)對(duì)象內(nèi)部及不同部分的訪問進(jìn)行結(jié)構(gòu)上的限制。

               1.適配器模式

                比如 class Point{

                           public double x;

                           public double y;

                           public synchronized double getX(){};

                          //……

                }

              采用對(duì)象限制的設(shè)計(jì)方式,會(huì)將synchronized 鎖移除到一個(gè)其他對(duì)象里,這樣就解脫了Point.

               like this

                     class SychPoint {

                           private final Point point=new Point();

                          public synchronized double getX(){point.x}

                   }

              class Point{

                           public double x;

                           public double y;

                           public double getX(){};

                }

              說白了就是采用適配器模式,改變了一下原來類的結(jié)構(gòu)。java.util.Collection framework 里面就是使用這種策略組織起集合類的同步。

             2.子類化

                 將鎖延遲到子類實(shí)現(xiàn),這里將不再羅嗦。

          二.同步設(shè)計(jì)

               使用鎖的注意事項(xiàng)

                 1.有些入口鎖在只有少數(shù)線程訪問的情況下,可以很好的工作,開銷并不大。但是當(dāng)并發(fā)量變大,競爭加劇,開銷也變大,系統(tǒng)的性能會(huì)隨之下降。大多數(shù)線程會(huì)把大部分時(shí)間浪費(fèi)在等待上。系統(tǒng)出現(xiàn)了延遲,限制了并發(fā)系統(tǒng)的優(yōu)越性。

                 2.使用太多的鎖,會(huì)增加系統(tǒng)負(fù)擔(dān),以及不可料的情況發(fā)生,比如死鎖。

                 3.只用一把鎖來保護(hù)一個(gè)功能的多個(gè)方面會(huì)導(dǎo)致資源競爭。

                 4.長時(shí)間持有鎖,會(huì)帶來性能問題和異常處理的復(fù)雜。

                 5.有時(shí)候加鎖并不一定能保證得到我們想要的結(jié)果。

              對(duì)付以上這些問題,沒有什么最佳策略,大都需要去權(quán)衡各個(gè)方面的利弊來進(jìn)行設(shè)計(jì)。寫多線程的程序,前期的設(shè)計(jì)比后期維護(hù)更為重要。

              初期的設(shè)計(jì)原則,

                  1.減少同步

                       a.用戶可以接受陳舊數(shù)據(jù),可以拿掉同步,使用volatile

                       b.用戶在得到非法數(shù)據(jù)時(shí),只要能得到提示就夠了,可以使用double-check方法。

                          在不同步時(shí)check一次,再在同步狀態(tài)在check一次。這么做的意義在于縮小鎖使用范圍,在第一次check不滿足的情況,跳出方法,那么鎖也就用不到了。

                       c.只對(duì)維護(hù)狀態(tài)部分加鎖:當(dāng)對(duì)象的某個(gè)同步方法是比較耗時(shí)的操作,那么鎖持有的時(shí)間就越長,而僅僅是為了保持一個(gè)狀態(tài)是,可以采用openCall的方式,減少持有鎖時(shí)間。

                                        public sychronized void updateState(){}

                                        public void readFile(){

                                                updateState();//持有鎖

                                              file.read();

                                         }

                         如上,這種方式的前提是程序不需要同步一個(gè)方法中無狀態(tài)的部分。如果整個(gè)方法都需要鎖,那這種方式就不適用了.

                      D.能使用同步塊,就不需同步整個(gè)方法。

               2.分解同步:

                  分解類

                      將鎖拆分到輔助類中

                  分解鎖

                     如果不愿分解類,可以設(shè)計(jì)分解鎖

                              private static Object lock1 = new Object();

                             private static Object  lock2 = new Object();

                            synchronize(lock1){}

                            synchronized(lock2){}

                        在jdk 5.0之后的并發(fā)包里,已有可重入鎖供使用。

                    隔離成員變量

                        Person的age,income等屬性都需要同步處理,以保證并發(fā)修改時(shí),可以設(shè)計(jì)一些同步的int,Double等類型(util.concurrent已提供類似的類),將鎖交給輔助類去處理。起到隔離作用.

           

          posted @ 2010-11-11 17:47 阮步兵 閱讀(1751) | 評(píng)論 (0)編輯 收藏

          主站蜘蛛池模板: 阳高县| 辉南县| 临朐县| 门源| 洛浦县| 连云港市| 中超| 新绛县| 罗定市| 金阳县| 保德县| 苍山县| 茂名市| 洪江市| 三原县| 凤冈县| 贵州省| 那坡县| 丹寨县| 南丹县| 平阴县| 故城县| 涞源县| 贡嘎县| 上高县| 仪征市| 班玛县| 仁化县| 商都县| 百色市| 繁峙县| 天等县| 新营市| 清丰县| 伊宁市| 报价| 河曲县| 舒城县| 惠安县| 济阳县| 瑞昌市|