Java

为什么JAVA要提供 wait/notify 机制?是为了避免轮询带来的性能损失

     我好土,真的。学用了四五年的JAVA,还从没用过 wait/notify,也不清楚它跟synchronized 关键字 相比有什么好处。今天查了些资料,终于明白了:wait/notify  机制是为了避免轮询带来的性能损失。     为了说清道理,我们用“图书馆借书”这个经典例子来作解释。     一本书同时只能借给一个人。现在有一本书,图书馆已经把这本书借了张三。     在简单的synchrnozed 同步机制下,李四如果想借,先要去图书馆查看书有没有还回来。李四是个心急的人,他每天都去图书馆查;而张三看书看得慢,过了半个月才把书还回来,结果李四在这半个月里全都白跑了,浪费了不少交通车费     而如果使用wait/notify机制,李四就不用白忙了。他第一次去图书馆时发现书已借走,就回家静静等待(wait);张三把书还掉后,通知(notify)李四,李四去图书馆拿书即可。整个过程中,李四没有白跑,没浪费钱。     回到计算机世界:            书           —  临界资源,需互斥地访问     张三,李四      —  两个竞争的线程 坐车去图书馆查书   —  轮询       车费          —  CPU空间       等待          —  wait   通知下一个借书者   —  notify     也就是说,若使用简单的synchonized机制实现互斥,会导致线程主动发起轮询,若N次轮询没有成功,就产生了N次的CPU空间浪费;如果加上了 wait/notify机制,就可以避免这些无谓的轮询,节省CPU的消耗。

CGLIB环境下,Properties.copyProperties()要慎用

Properties.copyProperties() 就是用来复制一个BEAN的所有属性 到 另一个BEAN 但如果其中一个BEAN是ProxyBean(如CGLIB实现的代理),那就很可能会出错,因为ProxyBean有其他一些 莫名奇妙 的属性,把这些属性搞给一个非Proxy的原Bean,就会出现“无此属性” 错误

注意:ftpClient某些方法是boolean方法

注意:ftpClient.login(), ftpClient.changeWorkingDirectory()都会返回boolean结果 如果用户名密码错误,ftpClient.login()并不会报异常,只是返回false 如果指定目录不存在,ftpClient.changeWorkingDirectory()不会报异常,只是返回false

new File().mkdirs()返回的true或false是怎么决定的?

例示: 假设系统只有一个硬盘,c:盘,且c盘下还没有 "hi"目录 //连续执行 new File("z:/hi").mkdirs();  //false,因为z盘不存在 new File("z:/hi").mkdirs();  //false,同上 //连续执行 new File("c:/hi").mkdirs();  //true new File("c:/hi").mkdirs();  //false,因为hi目录已经存在

[Spring]如果要从datasource里拿到connection并且使它自动被事务管理器掌管

今天偶然发现,如果使用了Spring框架,如果要从datasource里拿到connection并且使它自动被事务管理器掌管,则应该: Application code is required to retrieve the JDBC connection via DataSourceUtils.getConnection(DataSource) instead of J2EE’s standard DataSource.getConnection. 如果资源是JDBC 连接,则用DataSourceUtils 如果资源是JDO 连接,则用PersistenceManagerFactoryUtils 如果资源是Hibernate session,则用 SessionFactoryUtils

Hibernate: 设A引用了B,则删A后可能要evict(A.getB())

Hibernate: 设A引用了B,如果要先取A删A再取B删B,则删A后可能要evict(A.getB()),才能顺利删除B 否则,就会报错:a different object with the same identifier value was already associated with the session 原理是这样的:        第一步将A从数据库中取出时,它引用的B也从数据库中取出,两者同时成为持久化对象。A删除后,B是处于Session中的持久化对象       第二步中又显式地将B从数据库中取出,加上第一步中取出的B,Session里就有两个B了。这时侯如果删B,就会报上面所说的那种错误。        因此,应该在删除A后立即将它引用了的B从Session中清除掉。即:        A   =  Session.load(A);        Session.delete(A);        Session.evict(A.getB());        Session.delete(B); =============================================== 注意:evict()并不会级联,除非设置了相应的cascade 也就是说,如果B引用了C, evict(B)时不会自动evict(C) 看官方文档: This operation cascades to associated instances if the association is mapped with cascade="all" or cascade="all-delete-orphan".