scala雾中风景(13): 模式匹配中的逻辑或

bigbull_提的问题,说在看akka的源码时,模式匹配有这样的用法,之前没有看到过:

def isManagementMessage(msg: Any): Boolean = 
  msg match { 
    case _: AutoReceivedMessage | _: Terminated | _: RouterManagementMesssage ⇒ true 
    case _ ⇒ false 
  }

自己尝试:

val a = 1 
val b = a match { case _:String | _:Int => "str or int" } 

却报错。

这是模式匹配可以对多个条件一起匹配的情况。假设有2个case class定义如下:

scala> case class A(p1:Int, p2:Int)
defined class A

scala> case class B(p1:String, p2:String)
defined class B

现在我们想在模式匹配的时候,判断目标是否匹配A或B,可以这样写:

scala> def foo(msg:Any) = msg match { case A(_,2) | B(_,_) => println("ok") }
foo: (msg: Any)Unit

scala> foo(A(1,2))
ok

上面使用的是构造器模式混合通配符,如果我们不关心匹配时解构参数,只关心类型,可以用下面的方式来写:

scala> def foo(msg:Any) = msg match { case _:A | _:B => println("ok") }
foo: (msg: Any)Unit

scala> foo(A(1,2))
ok

这里注意,上面的类型匹配不能简化为 case _: A | B 因为这样写B代表的是伴生对象,是常量匹配:

scala> def foo(msg:Any) = msg match { case _:A | B => println("ok") }
foo: (msg: Any)Unit

scala> foo(A(1,2))
ok

scala> foo(B(1,2))
<console>:13: error: type mismatch;
found   : Int(1)
required: String
          foo(B(1,2))
                ^
scala> foo(B)
ok

上面的匹配表达式表示匹配A类型,或者B伴生对象(常量)。

而原先测试时,使用的

scala> val a = 1  // 这里已经推导a为Int类型
scala> val b = a match { case _:String | _:Int => "str or int" }
<console>:8: error: scrutinee is incompatible with pattern type;

这其实也可以给出警告而不是错误,scala编译器比较严格直接报错误了,要通过编译,可以把a的类型设置的泛一些:

scala> val a:Any = 1
a: Any = 1

scala> val b = a match { case _:String | _:Int => "str or int" }
b: String = str or int  

李昌钰博士的演讲

下午在公司的报告厅,听了李昌钰博士的《我的鑑識生涯—世际名案与學思歷程》,以前从未了解过这个行业,李博士的演讲也蛮有趣的,还记得几点:

1) 他提到昨天到广州,进酒店时已经晚上11点,准备今天的ppt和演讲到晚上2点,然后又坚持写书(每天写一页),虽然他这一页写的少了些只有几行,但让自己心安。

2) 证人的信息有40%是不可靠的。

3) 关于陈水扁枪击案,子弹水平划过肚皮,很多人觉得像是刀伤,但是有灼烧痕迹的。这是通过一把玩具枪改造的手枪,做枪的人把里面的枪栓换掉,这种枪杀伤力不大,但在短距离内还是有一些威胁的。使用自制子弹。打中吕秀莲腿部的是铜子弹,打中陈水扁的是铅子弹。嫌疑犯后来落水死亡,这个案子仍未结案。

4) 他的父亲是1949年乘坐太平轮从上海去往台湾时遇难的

家境原本还算富裕,父亲遇难后变得比较困难,所以他后来读书时选择读免费的警官学校。可能也是这个原因使他一直很尊敬和听从他妈妈的话,他演讲过程中提到过好几次别人邀请他做某个位置的职务时,他起先并不愿意,后来对方通过他的妈妈说服他。

tomcat每隔一小时full gc的问题

关于gc信息的收集,除了在启动时设置gclog选项,对于已经启动的java进程,也可以通过jstat去查看gc发生的原因。

$ jstat -gccause  java_pid 1s

S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
0.00 100.00  31.17  74.24  98.80      7    0.045     1    0.176    0.221 Allocation Failure   No GC
0.00 100.00  32.61  74.24  98.83      7    0.045     1    0.176    0.221 Allocation Failure   No GC
73.65   0.00  0.00  74.24  99.73      8    0.052     2    0.176    0.228 No GC      System.gc()
0.00   0.00   1.44  87.57  65.40      8    0.052     2    0.395    0.447 System.gc()          No GC
0.00   0.00   1.44  87.57  65.40      8    0.052     2    0.395    0.447 System.gc()          No GC
0.00   0.00   1.44  87.57  65.40      8    0.052     2    0.395    0.447 System.gc()          No GC

有一些应用周期性的发生full gc,即使没有多大访问量的情况,在tomcat里可能有2种原因:

1) 预防内存泄露的监听器 JreMemoryLeakPreventionListener 每隔一小时触发一次System.gc

Class clazz = Class.forName("sun.misc.GC");
Method method = clazz.getDeclaredMethod(
                        "requestLatency",
                        new Class[] {long.class});
method.invoke(null, Long.valueOf(3600000)); // 一小时

去看sun.misc.GCrequestLatency方法,传入的参数表示一次gc请求的延迟时间。会有个低优先级的daemon线程设置一个不超过这个延迟时间的object-inspection的周期

/**
 * Makes a new request for a garbage-collection latency of the given
 * number of real-time milliseconds.  A low-priority daemon thread makes a
 * best effort to ensure that the maximum object-inspection age never
 * exceeds the smallest of the currently active requests.
 *
 * @param   latency
 *          The requested latency
 *
 * @throws  IllegalArgumentException
 *          If the given <code>latency</code> is non-positive
 */
public static LatencyRequest requestLatency(long latency) {
    return new LatencyRequest(latency);
}

Daemon线程里,会在object-inspection周期之后执行System.gc()的。在tomcat 7028 和 6036 之后的版本里,把延迟时间调整了,不会再每小时调用一次了:

method.invoke(null, Long.valueOf(Long.MAX_VALUE - 1));

2) rmi.dgc 在JDK6里默认是1小时

参考这里,可以通过系统参数修改:

-Dsun.rmi.dgc.client.gcInterval=72000000
-Dsun.rmi.dgc.server.gcInterval=72000000

最近看过的电影(2)

《枪声俱乐部》(The Bang Bang Club)是无意中发现的一部值得一看的电影,让世界震惊的那张关于苏丹的照片:“秃鹫在一旁等待垂死的小女孩”的那张,就是出自这群战地摄影师。他们中有两位获得了普利策奖,当然他们也承受了巨大的代价。