Posts Tagged ‘java’

《Java Concurrency in Practice》

Sunday, May 18th, 2008

去了书店,看了《Java并发编程实践》,确实是一本不错的书,翻译的也不错。在书店只看了前三章 ,应该是整本书的基础。介绍Java中同步/互斥与共享的基本概念,同步/互斥其实是和语言不是很密切相关的,别的语言如C/C++都会遇到这个问题,但共享我却只在Java中看到,这个是Java平台(虚拟机)的实现约定,也就是多线程间共享变量时,一个线程写变量,另一个线程何时得到刷新的问题。以前从来没有想到Java会有这样的约定,挺奇怪的,应该是为了多CPU(或多核)的优化,幸而看了这本书。

后面的章节都没看,内容还很丰富,不过我向来认为这些技术类的书,应该先粗读一遍,理解概念,细节在用到时再看要好一些。基本上我觉得可以推荐一下这本书了,不错。

有好几天没有更新blog了,但生活还要继续,希望所有的人平平安安。

Java Volatile

Monday, May 12th, 2008

理解Java越多,就越发觉Java和C++的差异,这次是volatile。

共享
在C/C++中,volatile用于指示编译器对于这类变量的访问不要做优化,常用于一些硬件相关的读写中,在Java中,volatile的意思与C相似,但除了硬件相关外,还有一个更常见的使用场合,是用于多线程,在Java中,如果一个线程写变量,另一个线程读变量,读变量的线程可能不能“即时”获得被修改后的值,这是Java的一个实现约定,也是和JVM的实现相关,所以为了保证这种多线程共享变量的可见性,需要使用volatile。

互斥
要注意到,Java中synchronized也可以达到和volatile相同的作用,即使用synchronized做互斥时自动也达到了共享的目的,但反过来volatile就不能代替synchronized来做互斥,比如说非原子类型的变量(long/double之类)即使加volatile做++操作,也不是线程安全的,这时是需要使用synchronized的。

这样看来,Java中volatile的使用场合应该不是很多(因为多线程情况下,需要共享又不要互斥的情况不多),常见的使用诸如线程的控制循环退出的变量,一些标志变量等等,这些地方不涉及互斥,所以可以用volatile来简化。

Java线程与InterruptedException

Monday, May 5th, 2008

这个是Java中的一种异常,表示“被中断”,由于它是一个“checked exception”,所以在可能产生这种异常的场合下,你必须处理它。我一般看到的代码都是将之catch之后,什么也不做,为了确认这样的处理是否合适,找了一些资料来看,IBM Developerworks上的这篇文章做了比较详细的解释。

Java的线程都有一个interrupt标志,线程在运行时,如果别的线程想中断这个线程的运行(通过调用Thread.interrupt),会出现几种情况:

  • 当线程处于可以打断的阻塞状态,比如Thread.sleep()和Object.wait(),这时就会触发InterruptedException这个异常了,调用者必须处理一下这个异常,通常就是清理工作喽,或者继续往上抛,由调用者去决定后续的动作。
  • 当线程处于其它状态,比如努力干活,或虽然阻塞但不能被中断(比如一些IO操作),这时线程的中断状态位会被置位,剩下的事情就依赖线程自己的处理了,也就是说线程需要自己抽空来看这个标志位,如果不看的话,别人就没法打断你的运行了。

更多的细节,据说在《Java Concurrency in Practice》书中有详细的讲解(Amazon上5星哦),有些想看看,记得在书店应该是有中文版的《Java并发编程实践》,周末去看一看。

Java的互斥

Wednesday, April 30th, 2008

Java里做互斥还是很有意思的,不象C/C++,互斥依赖于平台实现。Java中的互斥是语言天生就提供的,Java有一个synchronized关键字,用来代替一般意义的lock/unlock,这样的好处起码是保证了lock/unlock的成对使用,另外代码看起来也清楚一些。而且Java里也不需要创建和删除互斥量,每个对象(Object)都带有一个互斥量,一般用这个就够用了。synchronized有好几种用法:

synchronized方法

这个是最常见的,直接在方法前面加synchronized,效果相当于进入方法时会lock这个对象,退出时unlock,这种方法加锁简单可靠,比如

public synchronized void method1(){

//do something under lock
}

但这种方法显然可能造成互斥区域扩大的风险,因为函数里的所有语句都自动放在互斥区内部了,这有时会影响效率。

synchronized语句

为了减小互斥区,可以直接使用synchronized语句,象这样:

private Object mutex = new Object();
public void method2(){
synchronized(mutex)
{
//do something under lock
}
//do otherthing
}

这种方法使用上更接近于C/C++的用法了,只是用一个Object来做互斥量了。

静态synchronized方法

语法上,Java也是支持在static method上加synchronized的,不过这就相当于lock了整个Class的锁了(非static的synchronized锁是基于对象的),粒度更大,这种用法我还没用过,书上如是说的。

最后,不要和Java1.5新的semphore混淆,Java1.5所提供的Semphore相当于大部分操作系统提供的计数器信号量,一般不用于做互斥(因为不能嵌套)。

J2ME的log

Saturday, April 26th, 2008

J2ME里面,直到MIDP2.0都没有Log的功能,本来不是大的问题,可以自己做一个嘛,不过在J2ME里面却不那么简单了,因为不知道把Log往哪里放,最常见的两个Log输出选项在J2ME都不具备(或者说不完全具备):

  • 控制台(console):大部分J2ME设备没有控制台,system.out.print的东东都会消失掉,不过Sun的模拟器倒是可以的,但毕竟是模拟器,没法进行设备上的调试。
  • 文件:这个要支持JSR75的设备才行,遗憾的是,很多设备都不支持(主要是早期的)。

所以,基本的做法只能是记在内存里,需要时把这个字符串取出来显示,不过这真不是一个好的解决方法,很简单的问题,如果代码崩溃了,就看不到的了。比较理想的一个方式是蓝牙(直接在PC端看Log),不过比记文件条件更高啊,需要两端都有蓝牙,并且设备端支持JSR82(N73好像支持),但起码我的笔记本还没有蓝牙。

Java Final vs C++ Const

Tuesday, April 1st, 2008

Java的Final看起来和C/C++的Const有几分相似,但又有很多不同,看了这篇文章后总结如下,Final有三种主要用法:

修饰变量:variable

final变量是不可改变的,但它的值可以在运行时刻初始化,也可以在编译时刻初始化,甚至可以放在构造函数中初始化,而不必在声明的时候初始化,所以下面的语句均合法:

  • final int i = 1; // 编译时刻
  • final int i2 = (int)(Math.Random() * 10); //运行时刻
  • final int i3; //构造函数里再初始化

而如果修饰类对象,并不表示这个对象不可更改,而是表示这个这个变量不可再赋成其它对象,这就比较象 C++的 Class const * p了。

 final Value v = new Value();
 v = new Value(); //不允许!
 v.some_method(); //允许

final经常和static一起用,这种用法类似C++的常量,在Java中很常见,比如 static final i = 10; 但这里同样也是允许运行时刻初始化的。

修饰方法:method

修饰方法时,final和C++的const就差别太大了,final表示一个Java函数不可更改,也就是不能被重载了,而不是修饰返回值的,所以private方法自动就是final的了(它们不会被重载)。

带来的一个附带的好处就是,final方法可以被编译器优化,比如内联什么的,也就是说final的方法可能效率会高一些(仅仅是可能,具体取决于编译器)。

修饰类:class

这个可以从final修饰方法引申开去,就表示整个类不能被继承了, 自然,里面的所有方法也相当于被加了final。

总之,final和const差别较大,还好Java换了一个关键字来做这些,否则会晕倒一批C++用户的,不过Java似乎保留了const这个字,不知留作什么用。

Java字节码编辑

Saturday, November 17th, 2007

Jad和ForntEnd Plus可以很好的反汇编Java程序,但得到的反汇编Java源码不一定能再编译(有一些代码是可以的,所以我不知道为什么有些就不行),这给有些h**k工作带来了障碍,幸好还有直接的Java字节码编辑程序可以用,比如:
Jbe: http://cs.ioc.ee/~ando/jbe/ 这个是直接针对Java的,比较轻量级,它自己也是Java实现的。
IDA:这个可是重量级的工具了,针对各种语言和平台,不过5.0以后的版本才对Java有较好的支持。

有了这些工具,哈哈,为所欲为啊。。。

Java 程序的启动脚本

Saturday, November 17th, 2007

由于Java程序的跨平台,很多Java程序可以不加修改的在Windows和Linux下运行,很多java程序是类似这样的脚本来启动的
java xx.yy.zz.aaaaaa

今天我遇到的一个程序,可能它是在Windows下开发的,当我将它放入Ubuntu下,它的启动脚本在Linux下却无法启动,报告方法找不到,原因其实很简单,DOS和Linux下文本文件对于回车的处理的不同,导致启动脚本在Linux下的行尾多了一个字符,用mc -e(一个Linux终端下的编辑器)可以看到,启动脚本变成了
java xx.yy.zz.aaaaaa^M

所以,,可以理解为什么启动不成功了,我想开发者可能是忘记了这个小小的差异了。

Robocode

Thursday, August 30th, 2007

很早以前在看一本Java的书的时候就知道Robocode这个项目, 非常有创意: 用Java实现一个 控制坦克的算法, 不同的算法坦克对战。你可以在网上下载到各种坦克,和自己坦克对战来提升自己坦克的战斗力,你还可以参加网上的坦克联赛,非常有趣!还可以看到排名,在1对1的排名表中,一位来自中国的坦克排在第16位。

在我的Ubuntu上,要先安装 sun-java5-jre(我试过sun-java6,不行,运行出错),然后切换java版本到sun-java:
sudo update-alternatives --config java
再使用官网上下载的setup文件来安装
java -jar  ./robocode-setup-1.4.2.jar
然后就ok了,在安装目录下运行robocode.sh,进入坦克世界吧!

其官网上的一句话非常精辟的概括了robocode:"Build the best - destroy the rest!"

C++/Java/Python/Ruby

Sunday, August 26th, 2007

这是一篇刚看的文章
http://www.dmh2000.com/cjpr/

基本上同意作者的观点,但是有两点重要不同,一是作者忘记了C,我认为C才是最佳的系统编程语言,而不是C++,另外一点,我不喜欢Ruby。

(c++的一个幽默: what is a protected abstract virtual base pure virtual private destructor?  )