jsr223-Java中的script引擎接口

分类:java评论:7条作者:ticmy日期:2012-09-04

JDK1.6开始,Java引入了jsr223,就是可以用一致的形式在JVM上执行一些脚本语言,如js。先来一个简单的例子以对在jvm上运行脚本有个初步的认识。 import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class TestScript1 { public static void main(String[] args) throws Exception { ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript"); String exp = "2*6-(6+5)"; Object result = scriptEngine.eval(exp); System.out.println(exp + "=" + result); } } 上面的例子是用来计算2*6-(6+5)这个表达式的值,使用了js引擎来计算,非常方便。另外,在工作流中,通常使用脚本引擎来计算一个节点到另一个节点之间的条件是否通过。如果不用脚本/表达式引擎,那就需要自己解析脚本了,若是算术算式,通常是构造成一个逆波兰式,这不是本文重点,就不展开了。 上面计算的表达式是“常量”,还可以计算带有变量的,如下: import javax.script.S…

闲聊ClassLoader

分类:java评论:5条作者:ticmy日期:2012-08-29

Java使用类加载器来装载字节码到内存,以便后续用来创建对象调用方法等。就目前的JVM,要说这个ClassLoader,先要说到它的委托模型(有人将parent译作双亲,双亲委派模型,窃以为,很不准确,原因在说完这个委托模型之后讲)。何为委托模型?java.lang.ClassLoader有这样的描述: 每个 ClassLoader 实例都有一个相关的父类加载器。 需要查找类或资源时,ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。 虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器,但是可以将它用作 ClassLoader 实例的父类加载器。 开始说“每个 ClassLoader 实例都有一个相关的父类加载器”,后面又说“虚拟机的内置类加载器(称为 “bootstrap class loader”)本身没有父类加载器”,这不是自行矛盾吗!其实不然,前面说的“每个 ClassLoader 实例”指的是每个java.lang.ClassLoader(该类是抽象类)子类的对象。而bootstrap class loader(后面叫它引导类加载器)是jvm内部由c++实现的,并不继承java.lang.ClassLoader类,所以它不属于“ClassLoader 实例”,也没有办法在Java代码…
Tags: ,

JDBC在getConnection之前为什么要调用Class.forName

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

获取一个数据库连接的通用模板如下: String driver = "oracle.jdbc.OracleDriver"; String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl"; String user = "scott"; String password = "ticmy"; Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, password); 里面有个Class.forName(driver),这句话有什么作用?将驱动类load到内存?如果没有这句会怎么样?运行发现,如果去掉这一句会有以下异常: java.sql.SQLException: No suitable driver found for xxx…. 在解释具体原因之前先简单看下Class.forName做了什么。 假设一个类以前从来没有被装进内存过,Class.forName(String className)这个方法会做以下几件事情: 1、装载。将字节码读入内存,并产生一个与之对应的java.lang.Class类对象 2、连接。这一步会验证字节码,为static变量分配内存,并赋默认值(0或null),并可选的解析符号引用(这里不理解没关系) 3、初始化。为类的static变量赋初始值,假如有static int a = 1;这个将a赋值为1的操作就是这个时候做的。除此之外,还要调用类的static…
Tags:

hotspot1.7 ThreadPoolExecutor代码解析

分类:java, 并发评论:5条作者:ticmy日期:2012-08-20

写在开头:此文基于hotspot1.7.0(build 1.7.0-b147),1.6及以前的版本与1.7的版本实现上差别很大。线程池的逻辑非常复杂,原因在于线程池是有状态的(不是狭隘的指RUNNING,SHUTDOWN这些状态,而是一个类的状态,可以理解成对象的共享字段),而为了保证可伸缩性与效率,很多地方在访问这些状态的时候都没有使用锁来保证互斥访问,而采用的是多次检测。这意味着会有很多竞态条件的出现,在分析某个方法的时候,要同时想到多线程间多个方法的交互,要考虑它们的交错执行。这里只分析核心重要的方法,其它方法相对简单,就不多言了。限于本人知识、眼界有限,对于一些代码逻辑的解释极可能没有考虑周全,错漏之处也在所难免。看官自己把握,也欢迎留言指正。 线程池内部有一些状态,先来了解下这些状态的机制。以下用代码注释的方式来解释其中的含义。 /* 这个是用一个int来表示workerCount和runState的,其中runState占int的高3位, 其它29位为workerCount的值。 workerCount:当前活动的线程数; runState:线程池的当前状态。 用AtomicInteger是因为其在并发下使用compareAndSet效率非常高; 当改变当前活动的线程数时只对低29位操作…

警惕hotspot1.6及之前ThreadPoolExecutor的bug

分类:java, 并发评论:5条作者:ticmy日期:2012-08-15

近来阅读ThreadPoolExecutor的源码(jdk版本:1.6.0_26),发现有些问题。毕竟是出自并发大神Doug Lea之手,不敢有过多质疑,经测试确实出现了不合理之处,并在后续版本中有修正。 发现两个问题,其中有一个比较严重。先讲这个比较严重的。 在ThreadPoolExecutor$Worker的run方法的源码如下: public void run() { try { Runnable task = firstTask; firstTask = null; while (task != null || (task = getTask()) != null) { runTask(task); task = null; } } finally { workerDone(this); } } 线程池里的线程在while里不停的去workQueue里取任务并执行任务。当在执行任务的时候(runTask中最重要的事情就是调用了传入的task的run方法),如果task的run抛出异常,runTask方法并没有吞掉该异常,它会继续往外抛,这会导致退出ThreadPoolExecutor$Worker#run中的while循环,并最终进入到finally中的workerDone方法,workerDone方法做了什么呢?源码如下: void workerDone(Worker w) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.comple…

Java中线程的创建

分类:java, 并发评论:7条作者:ticmy日期:2012-07-27

无论是网上还是一些书籍,包括Thread类的API文档中都写着创建线程有两种方式,一是extends Thread类,二是implements Runnable接口。然而,这种分类方式我很不喜欢,极易给一些人带来误解,让不少人以为implements Runnable接口就是创建了线程。 说“线程”在很多地方不容易分辨清楚,这里定义一个规则,下文说到“Java线程对象”的时候指的是java.lang.Thread类的一个对象,说到“可供CPU调度的线程”指的是一个真正可运行(或运行过)的线程。 先说说线程对象,在java.lang.Thread API中可以看到,目前其构造方法有8个,如下: public Thread() public Thread(Runnable target) public Thread(ThreadGroup group,Runnable target) public Thread(String name) public Thread(ThreadGroup group,String name) public Thread(Runnable target,String name) public Thread(ThreadGroup group,Runnable target,String name) public Thread(ThreadGroup group,Runnable target,String name,long stackSize) 创建一个Java线程对象目前有八种方式,可以传入很多参数以满足需求。实现了Runnable接口的类对象只是作为一个参…