按月存档: 2012/06

指定eclipse的启动jdk

分类:java, 基础评论:2条作者:ticmy日期:2012-06-30

在大部分时候,我们都使用PATH中指定的jdk来启动eclipse,但有些开发的时候需要多个jdk版本,比如ant要使用jdk1.5,某个eclipse需要用jdk1.6来启动(如开发android用的),这样在PATH里换来换去,好不麻烦。 这时候就需要指定eclipse的启动jdk功能了,只需在启动快捷方式改成这样即可:eclipse.exe -vm D:\program\java\jdk1.6.0_26\bin\javaw.exe。即通过-vm参数指定具体的javaw.exe的路径。 下载文章的PDF …
Tags:

《Java RMI》——流

分类:java, rmi评论:2条作者:ticmy日期:2012-06-30

读取字节和写入字节有两个基本的类,分别是InuputStream和OutputStream。两个类里的方法都很直接,具体含义方法及可直接参考API文档。 有个比较有趣的地方可能会让新手疑惑,在InputStream里有一个方法:public int read() throws IOException;这个方法表示读取一个字节,并返回。很多人会问,为什么返回值不是byte,而是一个int?原因在于“如果到达流的末尾,则返回 -1”。byte类型的-1的二进制补码是1111 1111,若使用byte类型作为返回值,则无法区分数据中的1111 1111还是流达到末尾的指示符。使用int后,所有数据中的字节反应到int中都是一个非负值,而只有流到达末尾的指示符是负值(-1)。与此对应的是OutputStream中的public abstract void write(int b) throws IOException方法,该方法写入一个字节,按理说这里不需要什么标识之类的东西,为什么要传入一个int呢?实际上,传入的int的有效范围只有[0,255](一个byte能表示的范围),如果超出这个范围,则会截断成一个byte。声明参数类型为int,是为了个前面说的read方法相对应,很可能你需要从InuputStream读取一个字节后将其写入到另外一个OutputStream,因为InuputStream那个read的返回值…
Tags: , ,

[翻译]字分裂(Word Tearing)

分类:java, 并发, 翻译评论:1条作者:ticmy日期:2012-06-11

《The Java Language Specification Java SE 7 Edition》§17.6 实现Java虚拟机需要考虑的一件事情是,字段之间以及数组元素之间是独立的,更新一个字段或元素不能影响任何其它字段或元素的读取与更新。尤其是,两个线程在分别更新byte数组相邻的元素时,不能互相影响与干扰,且不需要同步来保证顺序一致性。 有些处理器没有提供写单个字节的功能。在这样的处理器上更新byte数组,若只是简单地读取整个字,更新对应的字节,然后将整个字再写回内存,这种做法是违反规则的。这个问题有时候被称为“字分裂(word tearing)”,在单独更新单个字节有难度的处理器上,就需要寻求其它方式了。 例 17.6-1. 检测字分裂 下面的程序是一个检测字分裂的测试用例 public class WordTearing extends Thread { static final int LENGTH = 8; static final int ITERS = 1000000; static byte[] counts = new byte[LENGTH]; static Thread[] threads = new Thread[LENGTH]; final int id; WordTearing(int i) { id = i; } public void run() { byte v = 0; for (int i = 0;…

[翻译]非原子的double和long

分类:java, 并发, 翻译评论:1条作者:ticmy日期:2012-06-10

《The Java Language Specification Java SE 7 Edition》§17.7 为实现Java内存模型,对非volatile的long或double值的一次写操作是被当做两次独立地写操作来处理的:每次写一半——32位。这会导致一种情况,一个线程看到一个写操作写入的前32位,另一个写操作写入的后32位。 对volatile的long和double值的读与写总是原子的。 对引用的读与写总是原子的,不管它们是用32位还是64位实现的。 一些实现可以方便地将64位long或double值上的一次写操作分成相邻的32位值的两次写操作。 为提高效率,这种行为是特定于实现的;java虚拟机实现可以自由选择原子的或分成两次写入long或double值。 Java虚拟机规范鼓励尽可能避免分开处理64位值,同时鼓励程序员将共享的64位值声明为volatile或正确地使用同步以避免并发问题。 下载文章的PDF …

java中volatile的作用

分类:java, 并发评论:3条作者:ticmy日期:2012-06-06

java中volatile是一种弱同步。那么将一个变量声明为volatile,与非volatile有什么不同呢? 1、(jdk1.5之前没有这一条)提醒编译器和运行时环境,在volatile变量上的操作不能与其它操作重排序。譬如在new一个对象时,先分配空间,调用<clinit>方法(即static块和类变量初始化,按声明顺序排列),此时已经得到对象地址了,再在其上调用<init>方法(先对象属性初始化,再调用构造方法体)。那么在Person p = new Person(“abc”)的时候,有可能构造方法体还没有构造,p就已经被赋值了。在单线程环境下,这不会带来问题。但在多线程下,就有问题了,典型的问题就是单例模式的双重锁定检查问题,jdk1.4的时候,这种模式的单例是有问题的。 2、volatile变量不会缓存到CPU寄存器或cache中,确保变量的可见性。所以读取一个volatile变量的值总是返回其最近写入的值。 3、对于64位的long和double的操作是原子的(这里的原子指的是读取和赋值不会被分为两次进行,如a=1L,不会先写高32位,再写低32位,或相反的操作,确保其它线程不会获取到一个只写了一半的错误值)。jvm规范鼓励jvm实现者将long和double的操作作为原子性的,但这并不是强制性的,也就是说…

Integer与int解惑

分类:java, 基础评论:14条作者:ticmy日期:2012-06-06

jdk1.5引入了自动装箱(autoboxing)与自动拆箱(unboxing),这方便了集合类以及一些方法的调用,同时也使初学者对其感到非常之困惑。在此,我们来揭开其神秘的面纱。 首先,需要厘清一些概念: 1、Integer是一个类,用Integer声明一个变量其是一个对象类型(或者说引用类型);int是基本类型,用int声明的变量是非对象类型,即不能在其上调用方法。 2、“==”作用于对象上的时候,其比较的是对象的引用本身的值(或者说对象的地址更容易理解),而作用于基本类型的时候比较的就是基本类型的值。 接下来看一段代码: public class Test { public static void main(String[] args) { Integer i1 = 2; int i2 = 2; System.out.println(i1 == i2); } } 在这段代码中有两个令人困惑的问题,首先是将一个基本类型的值赋值给对象的引用,即Integer i1 =2;其次是拿一个对象类型和一个基本类型比较。按理说这两种做法肯定都是有问题的,在jdk1.4(若使用的jdk版本是1.5或之后的版本中,可以使用javac -source 1.4 Test.java来编译)上,确实如此,第一个问题在编译时会报“不兼容的类型”错误,第二个问题会报“运算符 == 不能应用于 java.lang.Integer…