按月存档: 2012/11

hotspot中Thread#isInterrupted的并发可见性bug

分类:java, 并发评论:2条作者:ticmy日期:2012-11-14

这是在concurrency-interest邮件列表看到的一个hotspot bug。 在《The Java Language Specification Java SE 7 Edition》中17.4.4Synchronization Order小节中有这么一句描述: If thread T1 interrupts thread T2, the interrupt by T1 synchronizes-with any point where any other thread (including T2) determines that T2 has been interrupted(by having an InterruptedException thrown or by invoking Thread.interrupted or Thread.isInterrupted). 线程t1 interrupt了线程t2,那么线程t2调用Thread.isInterrupted就会返回true,然而在hotspot几个版本中却没有体现出来,测试代码如下: public class InterruptedVisibilityTest { public void think() { System.out.println("新线程正在执行"); while (true) { if (checkInterruptedStatus()) break; } System.out.println("新线程退出循环"); } private boolean checkInterruptedStatus() { return Thread.currentThread().isInterrupted(); } public stati…

ScheduledThreadPoolExecutor与System#nanoTime

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

一直流传着Timer使用的是绝对时间,ScheduledThreadPoolExecutor使用的是相对时间,那么ScheduledThreadPoolExecutor是如何实现相对时间的? 先看看ScheduledThreadPoolExecutor中实现定时调度的模型,很简单,内部用了无界的DelayQueue作为线程池的队列,而DelayQueue的内部又使用的是一个PriorityQueue,那么,最先需要定时调度的任务位于队首。定时任务实现逻辑大概如此:创建ScheduledThreadPoolExecutor对象的时候会记录一个常量值t,定时任务中有一个以t为基础的多久以后会被执行的属性,在线程拿到队首任务(可能等待了一段时间)执行后,会修改这个属性为下一次要执行的基于t的时间量,然后将其再放入队列中。整个逻辑都在任务的run方法中: public void run() { if (isPeriodic()) runPeriodic(); else ScheduledFutureTask.super.run(); } 如果是周期性任务,会执行runPeriodic: private void runPeriodic() { boolean ok = ScheduledFutureTask.super.runAndReset(); boolean down = isShutdown(); // Reschedule if not cancelled and not shutdown or policy allows if (ok && (!down…

对象实例化的顺序

分类:java, 基础评论:6条作者:ticmy日期:2012-11-08

创建一个对象大概有以下几种方式: 1、通过new关键字,如new Object(); 2、通过某些反射类的newInstance方法,如Class#newInstance、Constructor#newInstance; 3、如果对象是Cloneable的,通过clone方法; 4、通过ObjectInputStream#readObject反序列化; 以上是通过java程序可以创建出对象的方式,jvm中还有一些隐式创建对象的地方,譬如: 1、启动一个类,main方法的参数String数组是隐式创建的,如果指定了一个或多个String对象,还要创建这些String对象; 2、读入一个class二进制数据的时候,创建一个与之对应的java.lang.Class类的对象; 3、在使用“+”进行字符串变量连接时,可能会创建StringBuffer/StringBuilder对象; 如此等等。 那么,在程序中通过new或newInstance创建对象(后面说创建对象均指这两种方式)的时候,构造方法、实例变量、父类构造方法、父类实例变量等的执行顺序是怎样的? 在创建对象的时候,首先会分配内存,此时所有实例变量均为默认值,然后做初始化实例变量、构造方法调用等操作。对于类变量,在创建对象之前,加载类的时候已经做掉了,这里为避免干扰,忽略掉。 先来一个例子: public class Init { public static v…