在路上

路上有惊慌,路上有理想

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  28 Posts :: 1 Stories :: 10 Comments :: 0 Trackbacks

2010年12月10日 #

1.linux安装字体
   以微软雅黑为例,找到msyh.ttf ,copy至下面的文件夹
   usr/share/fonts/msyh
  执行命令: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.如果需要根据字符串的长度生成图片的宽度,可以使用如下方法
 Rectangle2D bounds = font.getStringBounds(price, context);
 width = (int)(bounds.getWidth();

4.批量生成,使用java自带的线程池,并使用CompletionService,目的是在线程处理结束后得到生成成功的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 阮步兵 阅读(1839) | 评论 (0)编辑 收藏

以下只是一些概念


1.SemaphoreCountDownLatch
 
Semaphore 可用于控制特定资源请求(线程/操作)数量
 
CountDownLatch 在功能上类似于Semaphore。区别是,Semaphore允许一次一个线程的话,CountDownLatch可以允许多个线程在特定的时间一起执行。

2.CAS操作
  根据英文直译其实可以理解其含义,compare and set.

  CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。CAS 认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可通常将 CAS 用于同步的方式是从地址 V 读取值 A,执行多步计算来获得新值 B,然后使用 CAS 将 V 的值从 A 改为 B。如果 V 处的值尚未同时更改,则 CAS 操作成功。

3.ABA问题

  因为在更改 V 之前,CAS 主要询问“V 的值是否仍为 A”,所以在第一次读取 V 以及对 V 执行 CAS 操作之前,如果将值从 A 改为 B,然后再改回 A,会使基于 CAS 的算法混乱。在这种情况下,CAS 操作会成功,但是在一些情况下,结果可能不是您所预期的。这类问题称为 ABA 问题

4.原子操作

   A与B两个操作。从执行A的线程看,当其他线程执行B时,要么B全部执行完成,要么一点都不执行。这样A与B互为原子操作。要保证数据状态的一致性,要在单一的原子操作中更新所有相关联的状态。

5.可见性
 
   在单线程环境下,读写操作都在一个线程内完成,不存在可见性问题。但是,当读与写操作不在同一个线程内时,就需要有可见性的要求——即可变的共享变量对所有线程都是可见的。

6.重排序

    JVM实现中,线程内部维持顺序化语义。如果程序的最终结果等同于它在严格的顺序化环境下的结果,那么指令的执行顺序就可能与代码的顺序不一致。这个过程通过叫做指令的重排序。比如Java存储模型允许编译器重排序操作指令,在寄存器中缓存数值,还允许CPU重排序,并在处理器的缓存中缓存数值。

   当然,在没有同步的多线程情况下,编译器,处理器,运行时安排操作的执行顺序可能完全出人意料。

7.内部锁

  每个Java对象都可以隐士的扮演一个用于同步的锁的角色。比如synchronized(object){},执行线程进入synchronized块 之前自动获得锁。无论是正确执行或是抛出异常,最终都会释放该锁。内部锁是一种互斥锁(mutex)——至多只有一个线程可以拥有锁。JDK中有该锁的实 现。

8.锁与内存

   锁不仅仅是关于同步与互斥,也是关于内存可见性的。为了保证所有线程都能访问共享变量的最新值,读和写的线程必须使用公用的锁进行同步。

9.锁与volatile

   加锁可以保证可见性与原子性,volatile只能保证可见性。

10.happen-before法则

  Java存储模型有一个happens-before原则,就是如果动作B要看到动作A的执行结果(无论A/B是否在同一个线程里面执行),那么A/B就需要满足happens-before关系。比如一个对象构造函数的结束happens-before与该对象的finalizer的开始


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

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

     http://www.blogjava.net/xylz/archive/2010/07/03/325168.html

    《Java 并发编程实践》

posted @ 2010-12-15 18:18 阮步兵 阅读(1721) | 评论 (0)编辑 收藏

BTrace是一个实时监控工具,使用了java agent jvm attach技术,可以在product的情况下实时监控线上程序的运行情况。另,有插件可与visualVM一起使用。
不多说了,具体的可见:http://kenai.com/projects/btrace

下面介绍几个Helloworld示例:
主要使用了btrace命令:btrace [pid] class

pid可由jps命令快速查询

1.监控方法输入参数:
 @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);
            }

执行btract命令
后台输出:
com.btrace.Person
setId
[1, ]……

2.监控方法返回值
  @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();
       }
执行btract命令
后台输出:
getValue gum
com.btrace.TestThread.main(TestThread.java:23)

3.监控jvm内存使用情况
  @OnTimer(4000)
    public static void printMem() {
        println("Heap:");
        println(heapUsage());
        println("Non-Heap:");
        println(nonHeapUsage());
    }
执行btract命令
后台输出:
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.监控方法执行时间
   @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)));
    }
  后台输出:
   enter this method
   method end!
   Time taken ms0
5.监控Thread start
 @OnMethod(
        clazz="java.lang.Thread",
        method="start"
    )
    public static void func() {
        println("about to start a thread!");
    }
后台输出:about to start a thread!
posted @ 2010-12-10 18:30 阮步兵 阅读(3734) | 评论 (1)编辑 收藏