
2005年5月25日
最近在弄swing,需要由JComponent生成BufferedImage,在CSDN上發(fā)現(xiàn)一個(gè)好例子。下面是范例:
Rectangle?rect?=?comp.getBounds();
?BufferedImage?bufImage?=?new?BufferedImage(rect.width,
???????????rect.height,
???????????BufferedImage.TYPE_INT_RGB);
?Graphics?g?=?bufImage.getGraphics();
?g.translate(-rect.x,?-rect.y);
?comp.paint(g);這樣,JComponent中的圖像就保存到BufferedImage中了。
原文的鏈接:
http://dev.csdn.net/article/13/13531.shtm
??????? 好久沒(méi)有寫(xiě)blog了,距離上次寫(xiě)幾乎已經(jīng)是半年前的事情了。

?這半年發(fā)生了不少事情。首先換了家公司,進(jìn)了家金融企業(yè),每天要西裝革履的,一開(kāi)始還真是不習(xí)慣。

?這里開(kāi)發(fā)是用的spring框架,以后要多研究研究spring的東西了。
??????? 第二件事就是和戀愛(ài)了三年的女友結(jié)婚了,從此兩人長(zhǎng)相廝守,不知道時(shí)間久了會(huì)不會(huì)審美疲勞。呵呵。

??????? 第三件事就是在深圳買(mǎi)了自己的小房子,雖然是小小的兩房,不過(guò)我們已經(jīng)很知足了。

?而且剛好是趕在房?jī)r(jià)大漲前買(mǎi)的,還算走了點(diǎn)運(yùn)氣。換到現(xiàn)在,都不知道去哪里買(mǎi)好了。
??????? 在這里要向一些留言和發(fā)郵件給我的網(wǎng)友道歉,前段時(shí)間實(shí)在是太忙,沒(méi)有空回復(fù)你們的信息和郵件。請(qǐng)?jiān)彛?img height="20" src="/Emoticons/QQ/15.gif" width="20" border="0" />
最近真是多事情忙,而且可能要忙到9月底。好久沒(méi)有上來(lái)更新我的博客了,暫且發(fā)發(fā)牢騷。
這一節(jié)是非常實(shí)用的一節(jié),我在閱讀此書(shū)的時(shí)候,一直在迷惑,究竟應(yīng)該怎樣管理Session呢?因?yàn)镾ession的管理是如此重要,類(lèi)似于以前寫(xiě)程序?qū)DBC Connection的管理。看完此節(jié)后,終于找到了方法。
在各種Session管理方案中,ThreadLocal模式得到了大量使用。ThreadLocal是Java中一種較為特殊的線(xiàn)程綁定機(jī)制。通過(guò)ThreadLocal存取的數(shù)據(jù),總是與當(dāng)前線(xiàn)程相關(guān),也就是說(shuō),JVM為每個(gè)運(yùn)行的線(xiàn)程,綁定了私有的本定實(shí)例存取空間,從而為多線(xiàn)程環(huán)境經(jīng)常出現(xiàn)的并發(fā)訪(fǎng)問(wèn)問(wèn)題提供了一種隔離機(jī)制。
下面是Hibernate官方提供的一個(gè)ThreadLocal工具:
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import org.apache.log4j.Logger;


/**//**
* <p>Title: </p>
*
* <p>Description: Session的管理類(lèi)</p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: </p>
*
* @author George Hill
* @version 1.0
*/


public class HibernateUtil
{

private static final Logger log = Logger.getLogger(HibernateUtil.class);

private static final SessionFactory sessionFactory;


/**//**
* 初始化Hibernate配置
*/

static
{

try
{
// Create the SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();

} catch (Throwable ex)
{
log.error("Initial SessionFactory creation failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}

public static final ThreadLocal session = new ThreadLocal();


/**//**
* 根據(jù)當(dāng)前線(xiàn)程獲取相應(yīng)的Session
* @return Session
* @throws HibernateException
*/

public static Session currentSession() throws HibernateException
{
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet

if (s == null)
{
s = sessionFactory.openSession();
session.set(s);
}
return s;
}


/**//**
* 返回Session給相應(yīng)的線(xiàn)程
* @throws HibernateException
*/

public static void closeSession() throws HibernateException
{
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}

}

針對(duì)WEB程序,還可以利用Servlet2.3的Filter機(jī)制,輕松實(shí)現(xiàn)線(xiàn)程生命周期內(nèi)的Session管理。下面是一個(gè)通過(guò)Filter進(jìn)行Session管理的典型案例:

public class PersistenceFilter implements Filter
{
protected static ThreadLocal hibernateHolder = new ThreadLocal();


public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
hibernateHolder.set(getSession());

try
{


chain.doFilter(request, response);



} finally
{
Session session = (Session) hibernateHolder.get();

if (session != null)
{
hibernateHolder.set(null);

try
{
session.close();

} catch (HibernateException ex)
{
throw new ServletException(ex);
}
}
}
}


}
數(shù)據(jù)分頁(yè)顯示,是很多B/S系統(tǒng)會(huì)遇到的問(wèn)題。現(xiàn)在大多數(shù)主流數(shù)據(jù)庫(kù)都提供了數(shù)據(jù)部分讀取機(jī)制,而對(duì)于某些沒(méi)有提供相應(yīng)機(jī)制的數(shù)據(jù)而言,Hibernate也通過(guò)其它途徑實(shí)現(xiàn)了分頁(yè),如通過(guò)Scrollable ResultSet,如果JDBC不支持Scrollable ResultSet,Hibernate也會(huì)自動(dòng)通過(guò)ResultSet的next方法進(jìn)行記錄定位。Hibernate的Criteria、Query等接口提供了一致的方法設(shè)定分頁(yè)范圍。下面是書(shū)中的例子:
Criteria criteria = session.createCriteria(TUser.class);
Criteria.add(Expression.eq("age", "20"));
//從檢索結(jié)果中獲取第100條記錄開(kāi)始的20條記錄
criteria.setFirstResult(100);
criteria.setFetchSize(20); 不過(guò),我在測(cè)試的時(shí)候總是不能夠正常工作,把setFetchSize方法換成setMaxResults方法才行。換成最新的mysql-connector-java-3.1.10-bin-g.jar驅(qū)動(dòng)也是一樣。
Hibernate通過(guò)Lifecycle、Validatable接口制定了實(shí)體對(duì)象CRUD過(guò)程中的回調(diào)方式。
Lifecycle接口中的onSave、onUpdate、onDelete方法,如果返回true則意味著需要中止執(zhí)行相應(yīng)的操作過(guò)程。如果代碼運(yùn)行期間拋出了CallbackException,對(duì)應(yīng)的操作也會(huì)被中止。注意,不要試圖在這些方法中調(diào)用Session進(jìn)行持久化操作,這些方法中Session無(wú)法正常使用。
Validatable.validate方法將在實(shí)體被持久化之前得到調(diào)用以對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證。此方法在實(shí)體對(duì)象的生命周期內(nèi)可能被數(shù)次調(diào)用,因此,此方法僅用于數(shù)據(jù)本身的邏輯校驗(yàn),而不要試圖在此實(shí)現(xiàn)業(yè)務(wù)邏輯的驗(yàn)證。
Hibernate還引入了Interceptor,為持久化事件的捕獲和處理提供了一個(gè)非侵略性的實(shí)現(xiàn)。Interceptor接口定義了Hibernate中的通用攔截機(jī)制。Session創(chuàng)建時(shí)即可指定加載相應(yīng)的Interceptor,之后,此Session的持久化操作動(dòng)作都將首先經(jīng)由此攔截器捕獲處理。簡(jiǎn)單的加載范例如下:
SessionFactory factory = config.buildSessionFactory();
Interceptor it = new MyInterceptor();
session = sessionFactory.openSession(it); 需要注意的是,與Lifecycle相同,Interceptor的方法中不可通過(guò)Session實(shí)例進(jìn)行持久化操作。
有興趣的可以去參加看看,網(wǎng)址:
http://www.javachina.cn/Index.jsp
最近真是忙,事情都擠到一塊去了。
終于有時(shí)間又看了幾頁(yè)書(shū)。
言歸正傳,Hibernate中的Collection類(lèi)型分為有序集和無(wú)序集兩類(lèi)。這里所謂的有序和無(wú)序,是針對(duì)Hibernate數(shù)據(jù)持久過(guò)程中,是否保持?jǐn)?shù)據(jù)集合中的記錄排列順序加以區(qū)分的。無(wú)序集有Set,Bag,Map幾種,有序集有List一種。有序集的數(shù)據(jù)在持久化過(guò)程中,會(huì)將集合中元素排列的先后順序同時(shí)固化到數(shù)據(jù)庫(kù)中,讀取時(shí)也會(huì)返回一個(gè)具備同樣排列順序的數(shù)據(jù)集合。
Hibernate中的Collection類(lèi)型是用的自己的實(shí)現(xiàn),所以在程序中,不能夠把接口強(qiáng)制轉(zhuǎn)化成相應(yīng)的JDK Collection的實(shí)現(xiàn)。
結(jié)果集的排序有兩種方式:
1. Sort
Collection中的數(shù)據(jù)排序。
2. order-by
對(duì)數(shù)據(jù)庫(kù)執(zhí)行Select SQL時(shí),由order by子句實(shí)現(xiàn)的數(shù)據(jù)排序方式。
需要注意的是,order-by特性在實(shí)現(xiàn)中借助了JDK 1.4中的新增集合類(lèi)LinkedHashSet以及LinkedHashMap。因此,order-by特性只支持在1.4版本以上的JDK中運(yùn)行。
Session.get/load的區(qū)別:
1.如果未能發(fā)現(xiàn)符合條件的記錄,get方法返回null,而load方法會(huì)拋出一個(gè)ObejctNotFoundException。
2.Load方法可返回實(shí)體的代理類(lèi)類(lèi)型,而get方法永遠(yuǎn)直接返回實(shí)體類(lèi)。
3.Load方法可以充分利用內(nèi)部緩存和二級(jí)緩存中現(xiàn)有數(shù)據(jù),而get方法則僅僅在內(nèi)部緩存中進(jìn)行數(shù)據(jù)查找,如沒(méi)有發(fā)現(xiàn)對(duì)應(yīng)數(shù)據(jù),將越過(guò)二級(jí)緩存,直接調(diào)用SQL完成數(shù)據(jù)讀取。
Session.find/iterate的區(qū)別:
find方法將執(zhí)行Select SQL從數(shù)據(jù)庫(kù)中獲得所有符合條件的記錄并構(gòu)造相應(yīng)的實(shí)體對(duì)象,實(shí)體對(duì)象構(gòu)建完畢之后,就將其納入緩存。它對(duì)緩存只寫(xiě)不讀,因此無(wú)法利用緩存。
iterate方法首先執(zhí)行一條Select SQL以獲得所有符合查詢(xún)條件的數(shù)據(jù)id,隨即,iterate方法首先在本地緩存中根據(jù)id查找對(duì)應(yīng)的實(shí)體對(duì)象是否存在,如果緩存中已經(jīng)存在對(duì)應(yīng)的數(shù)據(jù),則直接以此數(shù)據(jù)對(duì)象作為查詢(xún)結(jié)果,如果沒(méi)有找到,再執(zhí)行相應(yīng)的Select語(yǔ)句獲得對(duì)應(yīng)的庫(kù)表記錄(iterate方法如果執(zhí)行了數(shù)據(jù)庫(kù)讀取操作并構(gòu)建了完整的數(shù)據(jù)對(duì)象,也會(huì)將其查詢(xún)結(jié)果納入緩存)。
Query Cache產(chǎn)生作用的情況:
1.完全相同的Select SQL重復(fù)執(zhí)行。
2.在兩次查詢(xún)之間,此Select SQL對(duì)應(yīng)的庫(kù)表沒(méi)有發(fā)生過(guò)改變。
Session.save方法的執(zhí)行步驟:
1.在Session內(nèi)部緩存中尋找待保存對(duì)象。內(nèi)部緩存命中,則認(rèn)為此數(shù)據(jù)已經(jīng)保存(執(zhí)行過(guò)insert操作),實(shí)體對(duì)象已經(jīng)處于Persistent狀態(tài),直接返回。
2.如果實(shí)體類(lèi)實(shí)現(xiàn)了lifecycle接口,則調(diào)用待保存對(duì)象的onSave方法。
3.如果實(shí)體類(lèi)實(shí)現(xiàn)了validatable接口,則調(diào)用其validate()方法。
4.調(diào)用對(duì)應(yīng)攔截器的Interceptor.onSave方法(如果有的話(huà))。
5.構(gòu)造Insert SQL,并加以執(zhí)行。
6.記錄插入成功,user.id屬性被設(shè)定為insert操作返回的新記錄id值。
7.將user對(duì)象放入內(nèi)部緩存。
8.最后,如果存在級(jí)聯(lián)關(guān)系,對(duì)級(jí)聯(lián)關(guān)系進(jìn)行遞歸處理。
Session.update方法的執(zhí)行步驟:
1.根據(jù)待更新實(shí)體對(duì)象的Key,在當(dāng)前session的內(nèi)部緩存中進(jìn)行查找,如果發(fā)現(xiàn),則認(rèn)為當(dāng)前實(shí)體對(duì)象已經(jīng)處于Persistent狀態(tài),返回。
2.初始化實(shí)體對(duì)象的狀態(tài)信息(作為之后臟數(shù)據(jù)檢查的依據(jù)),并將其納入內(nèi)部緩存。注意這里Session.update方法本身并沒(méi)有發(fā)送Update SQL完成數(shù)據(jù)更新操作,Update SQL將在之后的Session.flush方法中執(zhí)行(Transaction.commit在真正提交數(shù)據(jù)庫(kù)事務(wù)之前會(huì)調(diào)用Session.flush)。
Session.saveOrUpdate方法的執(zhí)行步驟:
1.首先在Session內(nèi)部緩存中進(jìn)行查找,如果發(fā)現(xiàn)則直接返回。
2.執(zhí)行實(shí)體類(lèi)對(duì)應(yīng)的Interceptor.isUnsaved方法(如果有的話(huà)),判斷對(duì)象是否為未保存狀態(tài)。
3.根據(jù)unsaved-value判斷對(duì)象是否處于未保存狀態(tài)。
4.如果對(duì)象未保存(Transient狀態(tài)),則調(diào)用save方法保存對(duì)象。
5.如果對(duì)象為已保存(Detached狀態(tài)),調(diào)用update方法將對(duì)象與Session重新關(guān)聯(lián)。
事務(wù)的4個(gè)基本特性(ACID):
1. Atomic(原子性):事務(wù)中包含的操作被看作一個(gè)邏輯單元,這個(gè)邏輯單元中的操作要么全部成功,要么全部失敗。
2. Consistency(一致性):只有合法的數(shù)據(jù)可以被寫(xiě)入數(shù)據(jù)庫(kù),否則事務(wù)應(yīng)該將其回滾到最初狀態(tài)。
3. Isolation(隔離性):事務(wù)允許多個(gè)用戶(hù)對(duì)同一個(gè)數(shù)據(jù)的并發(fā)訪(fǎng)問(wèn),而不破壞數(shù)據(jù)的正確性和完整性。同時(shí),并行事務(wù)的修改必須與其他并行事務(wù)的修改相互獨(dú)立。
4. Durability(持久性):事務(wù)結(jié)束后,事務(wù)處理的結(jié)果必須能夠得到固化。
數(shù)據(jù)庫(kù)操作過(guò)程中可能出現(xiàn)的3種不確定情況:
1. 臟讀取(Dirty Reads):一個(gè)事務(wù)讀取了另一個(gè)并行事務(wù)未提交的數(shù)據(jù)。
2. 不可重復(fù)讀取(Non-repeatable Reads):一個(gè)事務(wù)再次讀取之前的數(shù)據(jù)時(shí),得到的數(shù)據(jù)不一致,被另一個(gè)已提交的事務(wù)修改。
3. 虛讀(Phantom Reads):一個(gè)事務(wù)重新執(zhí)行一個(gè)查詢(xún),返回的記錄中包含了因?yàn)槠渌罱峤坏氖聞?wù)而產(chǎn)生的新記錄。
標(biāo)準(zhǔn)SQL規(guī)范中,為了避免上面3種情況的出現(xiàn),定義了4個(gè)事務(wù)隔離等級(jí):
1. Read Uncommitted:最低等級(jí)的事務(wù)隔離,僅僅保證了讀取過(guò)程中不會(huì)讀取到非法數(shù)據(jù)。上訴3種不確定情況均有可能發(fā)生。
2. Read Committed:大多數(shù)主流數(shù)據(jù)庫(kù)的默認(rèn)事務(wù)等級(jí),保證了一個(gè)事務(wù)不會(huì)讀到另一個(gè)并行事務(wù)已修改但未提交的數(shù)據(jù),避免了“臟讀取”。該級(jí)別適用于大多數(shù)系統(tǒng)。
3. Repeatable Read:保證了一個(gè)事務(wù)不會(huì)修改已經(jīng)由另一個(gè)事務(wù)讀取但未提交(回滾)的數(shù)據(jù)。避免了“臟讀取”和“不可重復(fù)讀取”的情況,但是帶來(lái)了更多的性能損失。
4. Serializable:最高等級(jí)的事務(wù)隔離,上面3種不確定情況都將被規(guī)避。這個(gè)級(jí)別將模擬事務(wù)的串行執(zhí)行。
Hibernate將事務(wù)管理委托給底層的JDBC或者JTA,默認(rèn)是基于JDBC Transaction的。
Hibernate支持“悲觀鎖(Pessimistic Locking)”和“樂(lè)觀鎖(Optimistic Locking)”。
悲觀鎖對(duì)數(shù)據(jù)被外界修改持保守態(tài)度,因此,在整個(gè)數(shù)據(jù)處理過(guò)程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫(kù)提供的鎖機(jī)制。Hibernate通過(guò)使用數(shù)據(jù)庫(kù)的for update子句實(shí)現(xiàn)了悲觀鎖機(jī)制。Hibernate的加鎖模式有:
1. LockMode.NONE:無(wú)鎖機(jī)制
2. LockMode.WRITE:Hibernate在Insert和Update記錄的時(shí)候會(huì)自動(dòng)獲取
3. LockMode.READ:Hibernate在讀取記錄的時(shí)候會(huì)自動(dòng)獲取
4. LockMode.UPGRADE:利用數(shù)據(jù)庫(kù)的for update子句加鎖
5. LockMode.UPGRADE_NOWAIT:Oracle的特定實(shí)現(xiàn),利用Oracle的for update nowait子句實(shí)現(xiàn)加鎖
樂(lè)觀鎖大多是基于數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn)。Hibernate在其數(shù)據(jù)訪(fǎng)問(wèn)引擎中內(nèi)置了樂(lè)觀鎖實(shí)現(xiàn),可以通過(guò)class描述符的optimistic-lock屬性結(jié)合version描述符指定。optimistic-lock屬性有如下可選取值:
1. none:無(wú)樂(lè)觀鎖
2. version:通過(guò)版本機(jī)制實(shí)現(xiàn)樂(lè)觀鎖
3. dirty:通過(guò)檢查發(fā)生變動(dòng)過(guò)的屬性實(shí)現(xiàn)樂(lè)觀鎖
4. all:通過(guò)檢查所有屬性實(shí)現(xiàn)樂(lè)觀鎖
現(xiàn)在搜狐新聞上報(bào)道已經(jīng)有700多人傷亡,這是自從911事件以后最大的一次恐怖襲擊了。現(xiàn)在這個(gè)世界,是越來(lái)越不太平了,貧富差距的加大使得恐怖活動(dòng)有生存的土壤。
不知道世界的經(jīng)濟(jì)會(huì)不會(huì)隨著這次恐怖襲擊而開(kāi)始走向蕭條。現(xiàn)在的地球越來(lái)越像一個(gè)村,發(fā)生在任何一個(gè)角落的事情,都有可能會(huì)影響到每一個(gè)人。
昨晚偶然看見(jiàn)國(guó)際臺(tái)播放星戰(zhàn)的作者喬治盧卡斯榮獲AFI終身成就獎(jiǎng)的頒獎(jiǎng)典禮,耐心的看完了整個(gè)頒獎(jiǎng)典禮。喬治在發(fā)表致詞的時(shí)候,說(shuō)自己很高興能夠從事自己喜歡的電影工作,如果不拍攝電影,都不知道自己還能夠做什么。拍電影已經(jīng)成了喬治生命的一部分。
看到熒屏上全世界的老人,中年人,年輕人,孩子說(shuō)著:“Thank you! George.”可以看到喬治的眼睛朦朧。我心中真是感慨,每個(gè)人都有自己的夢(mèng)想,能夠從事自己喜歡的事情,確實(shí)是很開(kāi)心的一件事。而自己所做的工作,能夠給自己帶來(lái)快樂(lè),能夠給人們帶來(lái)快樂(lè),這樣的工作才值得用一生的時(shí)間去從事。
每一個(gè)登山者都有著自己心目中最想登上的山頂,能夠登上這個(gè)山頂,前面付出的艱辛都是值得的。人生不也如此么?找到自己喜歡從事的事情,用自己畢生的精力去做這件事。
獻(xiàn)出一份愛(ài)心 共同援助重病程序員王俊 |
(2005.06.27) 來(lái)自:BJUG |
|
|
|
|
向IT界倡議:援助程序員王俊行動(dòng)
王俊,今年27歲,北京北方銀證公司項(xiàng)目經(jīng)理,是北京Java用戶(hù)組(BJUG, 員(http://forum.javaeye.com/profile.php?mode=viewprofile&u=33)。一個(gè)年輕 人,有感興趣的工作,不錯(cuò)的前途,還有一群可以隨時(shí)交流技術(shù)的朋友,生活看起來(lái)平 淡卻充實(shí)。
業(yè)余時(shí)間,王俊經(jīng)常還利用blog(http://befresh.blogbus.com)寫(xiě)下自己生活和工作 中的酸甜苦辣,此外他還有一個(gè)并不富裕但卻很溫馨的家。
然而從今年二月份起,王俊的blog就再也沒(méi)有更新過(guò)了,他也沒(méi)有在BJUG的聚會(huì)和 javaeye出現(xiàn)了,所有人都以為他出差去了。直到最近,驚聞他要換骨髓,才知道今年 年初,王俊被查出患有“骨髓增生異常綜合癥”。
骨髓增生異常綜合征目前認(rèn)為是造血干細(xì)胞增殖分化異常所致的造血功能障礙。主要表 現(xiàn)為外周血全血細(xì)胞減少,骨髓細(xì)胞增生,成熟和幼稚細(xì)胞有形態(tài)異常即病態(tài)造血。部 分患者在經(jīng)歷一定時(shí)期的MDS后轉(zhuǎn)化成為急性白血病;部分因感染、出血或其他原因死 亡,病程中始終不轉(zhuǎn)化為急性白血病。
這種病目前最有效的治療手段是換骨髓。萬(wàn)幸的是,王俊的妹妹和他的骨髓配型一致, 免疫系統(tǒng)的疾病發(fā)現(xiàn)治療的越早,就越可能成功,他目前的身體狀況還好,只要能更換 骨髓,完全可以康復(fù)!但讓他們一家望而卻步的是,僅手術(shù)押金就需要20萬(wàn),全部療程 視治療效果可能需要30-100萬(wàn)。
王俊的家在浙江杭州千島湖,父母都是農(nóng)民,已然老邁且沒(méi)有固定的經(jīng)濟(jì)收入,姐姐在 當(dāng)?shù)爻黾蓿杖腩H低,妹妹目前在北京讀成人教育并在公司打工。王俊是家庭經(jīng)濟(jì)主要 來(lái)源,他的病不僅掐斷了家里唯一的經(jīng)濟(jì)來(lái)源,還要花上對(duì)他們而言是天文數(shù)字的錢(qián)來(lái) 治病。
"文章千古事,得失寸心知",這是王俊blog上的座右銘。細(xì)細(xì)翻看這個(gè)典型程序員的 blog,就和他的人一樣樸實(shí)無(wú)華,在那里滿(mǎn)眼看到的都是對(duì)技術(shù)的孜孜追求。誰(shuí)能想到 一個(gè)如此活躍的頭腦現(xiàn)在卻被病魔折磨著。
生命是美好的,這世界每天都有若干悲劇發(fā)生,這次,大家每個(gè)人出一份力,這世界就 會(huì)少一個(gè)悲劇,多一份美好,多一份歡笑。也許,你只是少吃一頓大餐,少買(mǎi)一瓶化妝 品,少看一場(chǎng)演唱會(huì),少買(mǎi)一件名牌服裝,少玩一個(gè)月的網(wǎng)絡(luò)游戲,少上一個(gè)月的網(wǎng), 但是你卻可以為一個(gè)家庭托起一份生的希望。
*****
聯(lián)系方式 郵件 help@bjug.org MSN icecloud@sina.com 冰云(BJUG)
援助辦法:
1 捐款 帳號(hào): 工商銀行 戶(hù)名 王俊 帳號(hào) 0200 2008 0102 3428 807 開(kāi)戶(hù)行 工商銀行北京市西內(nèi)所
招商銀行 戶(hù)名 王俊 帳號(hào) 9555 5001 0200 2820 開(kāi)戶(hù)行 招商銀行 北京分行
中國(guó)銀行 戶(hù)名 王俊 帳號(hào) 4021400-0188-001204-0 開(kāi)戶(hù)行 北京西直門(mén)支行
國(guó)外匯款方式 ADD: BANK OF CHINA BEIJING BRANCH NO.8 YA BAO LU BEIJING, CHINA SWIFT-CODE: BKCHCNBJ110 A/CNo: 4021400-0188-001204-0 NAME: WANG JUN
捐款方式: A 網(wǎng)上銀行 工行請(qǐng)采用行內(nèi)匯款->有收款帳號(hào)匯款 招行請(qǐng)采用個(gè)人銀行專(zhuān)業(yè)版的同城轉(zhuǎn)帳/異地匯款,并選中:采用系統(tǒng)內(nèi)快速匯款
B 銀行匯款 請(qǐng)抄錄上述帳號(hào)并到銀行填寫(xiě)匯款單
請(qǐng)?jiān)诰杩詈螅l(fā)郵件至help@bjug.org,通知我們,以便統(tǒng)計(jì)核對(duì)捐款帳目。郵件中請(qǐng)說(shuō)明以下信息: (1) 姓名, (2) id/網(wǎng)站, (3) 發(fā)出銀行/發(fā)出帳號(hào), (4) 金額, (5) 時(shí)間
2 幫助宣傳:
- 請(qǐng)到http://befresh.bjug.org 留下你對(duì)他的祝福
- 請(qǐng)?jiān)贛SN上修改您的名字,我們都寫(xiě)上 [祝福后山]
- 請(qǐng)修改您MSN的頭像為我們提供的圖標(biāo)
- 增加行動(dòng)網(wǎng)站的地址 http://befresh.bjug.org 到MSN名字后面的個(gè)人信息
- 請(qǐng)看到此文的Blogger,在您的blog上link此文,并Trackback到后山的blog
- 請(qǐng)看到此信息的人,幫助一起宣傳,我們需要您的幫助
- 在您的BLOG或網(wǎng)站,加上用我們提供的LOGO,并連接到網(wǎng)站http://befresh.bjug.org
- 泡論壇的,請(qǐng)修改你的論壇LOGO和簽名檔為提供的圖標(biāo)

*****
聯(lián)合發(fā)起: BJUG http://www.bjug.org <http://www.bjug.org/> CSDN http://www.csdn.net <http://www.csdn.net/> JavaEye http://www.javaeye.com <http://www.javaeye.com/> JActionGroup http://www.jactiongroup.net/ Huihoo http://www.huihoo.org <http://www.huihoo.org/> RedSaga http://www.redsaga.com <http://www.redsaga.com/> Matrix http://www.matrix.org.cn <http://www.matrix.org.cn/> Blogbus http://www.blogbus.com <http://www.blogbus.com/> |
摘要: 要將BufferedImage實(shí)例保存為BMP文件,就需要知道BMP文件的格式,可以參考我轉(zhuǎn)載的文章:《BMP文件格式》。 下面是我的將BufferedImage實(shí)例保存為24位色BMP文件的實(shí)現(xiàn)。 ...
閱讀全文
在公元2005年6月27日,我做出了一個(gè)重大的決定,買(mǎi)房!花了自己至今為止都沒(méi)有見(jiàn)過(guò)的那么多的錢(qián)買(mǎi)了一個(gè)小小的2房2廳,

從此變成了“負(fù)翁”。
不過(guò),從此以后再也不用去租房,再也不用幫別人供房,再也不用一年搬一次家。深圳租房實(shí)在太貴,蓮花北的一個(gè)小小的二房都要1800,有點(diǎn)裝修就叫豪華裝修,就是一個(gè)空蕩蕩的房子也開(kāi)口要1500,太夸張了。住農(nóng)民房又極度不安全,不想拿自己的生命開(kāi)玩笑。
從此就變成月供一族了,

,不過(guò),有了壓力才有動(dòng)力。為了自己的將來(lái),自己的理想,努力奮斗!
9月26日是入伙的日子,好期待那天的到來(lái)啊。
一般而言,ORM的數(shù)據(jù)緩存應(yīng)包含如下幾個(gè)層次:
1. 事務(wù)級(jí)緩存(Transcation Layer Cache)
2. 應(yīng)用級(jí)/進(jìn)程級(jí)緩存(Application/Process Layer Cache)
3. 分布式緩存(Cluster Layer Cache)
Hibernate數(shù)據(jù)緩存(Cache)分為兩個(gè)層次,以Hibernate語(yǔ)義加以區(qū)分,可分為:
1. 內(nèi)部緩存(Session Level,也稱(chēng)為一級(jí)緩存)
2. 二級(jí)緩存(SessionFactory Level,也稱(chēng)為二級(jí)緩存)
Hibernate中,緩存將在以下情況中發(fā)揮作用:
1. 通過(guò)id[主鍵]加載數(shù)據(jù)時(shí)
2. 延遲加載
內(nèi)部緩存正常情況下由Hibernate自動(dòng)維護(hù),如果需要手動(dòng)干預(yù),可以通過(guò)以下方法完成:
1. Session.evict
將某個(gè)特定對(duì)象從內(nèi)部緩存清除。
2. Session.clear
清空內(nèi)部緩存。
在Hibernate中,二級(jí)緩存涵蓋了應(yīng)用級(jí)緩存和分布式緩存領(lǐng)域。如果數(shù)據(jù)滿(mǎn)足以下條件,則可將其納入緩存管理。
1. 數(shù)據(jù)不會(huì)被第三方應(yīng)用修改;
2. 數(shù)據(jù)大小(Data Size)在可接收的范圍之內(nèi);
3. 數(shù)據(jù)更新頻率較低;
4. 同一數(shù)據(jù)可能會(huì)被系統(tǒng)頻繁引用;
5. 非關(guān)鍵數(shù)據(jù)(關(guān)鍵數(shù)據(jù),如金融帳戶(hù)數(shù)據(jù))。
Hibernate本身并未提供二級(jí)緩存的產(chǎn)品化實(shí)現(xiàn),而是為眾多的第三方緩存組件提供了接入接口,較常用的第三方組件有:
1. JCS
2. EHCache
3. OSCache
4. JBossCache
5. SwarmCache
Hibernate中啟用二級(jí)緩存,需要在hibernate.cfg.xml配置hibernate.cache.provider_class參數(shù),之后,需要在映射文件中指定各個(gè)映射實(shí)體(以及collection)的緩存同步策略。Hibernate提供了一下4種內(nèi)置的緩存同步策略:
1. read-only
只讀。對(duì)于不會(huì)發(fā)生改變的數(shù)據(jù),可使用只讀型緩存。
2. nonstrict-read-write
如果程序?qū)Σl(fā)訪(fǎng)問(wèn)下的數(shù)據(jù)同步要求不是非常嚴(yán)格,且數(shù)據(jù)更新操作頻率較低,可以采用本選項(xiàng),獲得較好的性能。
3. read-write
嚴(yán)格可讀寫(xiě)緩存。基于時(shí)間戳判定機(jī)制,實(shí)現(xiàn)了“read committed”事務(wù)隔離等級(jí)。可用于對(duì)數(shù)據(jù)同步要求嚴(yán)格的情況,但不支持分布式緩存。這也是實(shí)際應(yīng)用中使用最多的同步策略。
4. transactional
事務(wù)型緩存,必須運(yùn)行在JTA事務(wù)環(huán)境中。
在Java語(yǔ)言中,對(duì)象之間的比較可以通過(guò)引用比較(==)和內(nèi)容比較(equals)兩種方式進(jìn)行,而在Hibernate的實(shí)體對(duì)象的比較是通過(guò)主鍵值來(lái)比較,如果要實(shí)現(xiàn)自己的識(shí)別邏輯,則需要重寫(xiě)equals方法和hashCode方法。
檢查數(shù)據(jù)對(duì)象改變檢查的一般策略有下面兩種:
1. 數(shù)據(jù)對(duì)象監(jiān)控
數(shù)據(jù)對(duì)象監(jiān)控的實(shí)現(xiàn)方式,通過(guò)攔截器對(duì)數(shù)據(jù)對(duì)象的設(shè)值方法進(jìn)行攔截。一旦數(shù)據(jù)對(duì)象的設(shè)置方法被調(diào)用,則將其標(biāo)志為“待更新”狀態(tài),之后在數(shù)據(jù)庫(kù)操作時(shí)將其更新到對(duì)應(yīng)的庫(kù)表。
2. 數(shù)據(jù)版本對(duì)比
在持久層框架中維持?jǐn)?shù)據(jù)對(duì)象的最近讀取版本,當(dāng)數(shù)據(jù)提交時(shí)將提交數(shù)據(jù)與此版本進(jìn)行比對(duì),如果發(fā)生變化則將其同步到數(shù)據(jù)庫(kù)對(duì)應(yīng)的庫(kù)表。
Hibernate采取的是第二種檢查策略。它采用一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)"EntityEntry"保存對(duì)應(yīng)實(shí)體類(lèi)的狀態(tài)信息。
對(duì)于級(jí)聯(lián)對(duì)象的更新,Hibernate將根據(jù)unsaved-value進(jìn)行判定。首先Hibernate會(huì)取出目標(biāo)對(duì)象的id。之后,將此值與unsaved-value進(jìn)行比對(duì),如果相等,則認(rèn)為目標(biāo)對(duì)象尚未保存,否則,認(rèn)為對(duì)象已經(jīng)保存,無(wú)需再進(jìn)行保存操作。
最近正在研讀《深入淺出Hibernate》一書(shū),前面寫(xiě)的隨筆有些也是讀該書(shū)的筆記,只是未做歸類(lèi),從這篇開(kāi)始,我將把相關(guān)的內(nèi)容都整理成一個(gè)系列的讀書(shū)筆記。
今天這篇是有關(guān)實(shí)體對(duì)象的生命周期。我剛開(kāi)始接觸Hibernate的時(shí)候,只是簡(jiǎn)單的把它當(dāng)做一個(gè)API工具,直到后來(lái)看到有關(guān)VO和PO的內(nèi)容時(shí),才意識(shí)到Hibernate不僅僅是一個(gè)O/R Mapping的API工具,它還是一個(gè)容器。它可以幫你管理實(shí)體對(duì)象的生命周期。
實(shí)體對(duì)象的生命周期有三種狀態(tài):
1.Transient(自由狀態(tài))
此時(shí)的實(shí)體對(duì)象和數(shù)據(jù)庫(kù)中的記錄無(wú)關(guān)聯(lián),只是一個(gè)普通的JavaBean。
2.Persistent(持久狀態(tài))
此時(shí)的實(shí)體對(duì)象和數(shù)據(jù)庫(kù)中的記錄有關(guān)聯(lián),其變更將由Hibernate固化到數(shù)據(jù)庫(kù)中。該實(shí)體對(duì)象處于由Hibernate框架所管理的狀態(tài)。
3.Detached(游離狀態(tài))
處于Persistent狀態(tài)的對(duì)象,其對(duì)應(yīng)的Session實(shí)例關(guān)閉之后,那么,此對(duì)象就處于"Detached"狀態(tài)。Detached狀態(tài)和Transient狀態(tài)的區(qū)別在于Detached狀態(tài)的對(duì)象可以再次與某個(gè)Session實(shí)例相關(guān)聯(lián)而成為Persistent對(duì)象。
從實(shí)體對(duì)象是否被納入Hibernate實(shí)體管理容器的角度,Transient和Detached狀態(tài)的實(shí)體對(duì)象可以統(tǒng)稱(chēng)為VO(Value Object),而被管理的實(shí)體對(duì)象稱(chēng)為PO(Persistent Object)。兩者的區(qū)別:
1.VO是相對(duì)獨(dú)立的實(shí)體對(duì)象,處于非管理狀態(tài)。
2.PO是Hibernate納入其實(shí)體管理容器(Entity Map)的對(duì)象,它代表了與數(shù)據(jù)庫(kù)中某條記錄對(duì)應(yīng)的Hibernate實(shí)體,PO的變化在事務(wù)提交時(shí)將反映到實(shí)際數(shù)據(jù)庫(kù)中。
3.如果一個(gè)PO與其對(duì)應(yīng)的Session實(shí)例分離,那么此時(shí),它又會(huì)變成一個(gè)VO。
下圖是我畫(huà)的實(shí)體對(duì)象生命周期的狀態(tài)轉(zhuǎn)換圖:
在使用HQL查詢(xún)中,有時(shí)并不需要獲取完整的一個(gè)實(shí)體對(duì)象,例如一個(gè)實(shí)體對(duì)象User有三個(gè)屬性:account, password和email,如果我們只需要獲取account和email屬性,那么有兩種方法可以選擇。
1. 用普通的"select user.account, user.email from User as user",程序片斷如下:
List list = session.createQuery("select user.account, user.email from User as user").list();
Iterator it = list.iterator();

while (it.hasNext())
{
Object[] values = (Object[]) it.next();
System.out.println(values[0] + " " + values[1]);
} 這時(shí)調(diào)用Query類(lèi)的list方法返回的將是一個(gè)每個(gè)元素都是一個(gè)Object數(shù)組的List。如果只獲取一個(gè)屬性,那么返回的List中的每個(gè)元素都是String實(shí)例。
2.在HQL中用new操作符生成實(shí)體對(duì)象,例如:"select new User(user.account, user.email) from User as user",程序片斷如下:
List list = session.createQuery("select new User(user.account, user.email) from User as user").list();
Iterator it = list.iterator();

while (it.hasNext())
{
User user = (User) it.next();
System.out.println(user.getAccount() + " " + user.getEmail());
} 這時(shí)list方法返回的List中的每一個(gè)元素都是User實(shí)體對(duì)象。這里有三點(diǎn)需要注意的:
a.在HQL語(yǔ)句中需要使用as操作符指定User的別名,并且需要在構(gòu)造函數(shù)的屬性前面加上別名;
b.HQL語(yǔ)句中的構(gòu)造函數(shù)在User類(lèi)中必須要有相應(yīng)的構(gòu)造函數(shù);
c.生成的實(shí)體對(duì)象是VO對(duì)象,如果對(duì)這些對(duì)象調(diào)用Session的saveOrUpdate方法將導(dǎo)致插入新的記錄,而不是更新記錄。
JBuilder 2005中多了一個(gè)Smart MemberInsight功能,這個(gè)功能會(huì)智能的匹配需要調(diào)用的方法或者獲取的屬性。例如有一個(gè)賦值操作,左邊是一個(gè)List,右邊是用一個(gè)方法獲取值,那么當(dāng)輸入"."時(shí),JBuilder 2005會(huì)自動(dòng)的找到所有返回的值為L(zhǎng)ist的方法。
不過(guò),這實(shí)在是一個(gè)不怎么討好的方法。因?yàn)楹芏鄷r(shí)候并不是只有一層方法調(diào)用的,例如,當(dāng)需要用一個(gè)方法獲取一個(gè)實(shí)例,然后再用這個(gè)實(shí)例的方法獲取需要的值時(shí),這個(gè)功能就顯得很礙手了。
終于,我還是決定關(guān)閉這個(gè)“智能”的功能。打開(kāi)"Tools"——>"Preferences",在"Editor"的子項(xiàng)"CodeInsight"里,展開(kāi)"MemberInsight",把"Default to Smart MemberInsight"這一項(xiàng)去掉。如下圖所示:
這個(gè)范例說(shuō)明如何用JFreeChart畫(huà)簡(jiǎn)單的柱狀圖,下面是一個(gè)JSP的簡(jiǎn)單范例:
<%@ page contentType="text/html; charset=GB2312" %>
<%@ page import="java.awt.*, java.text.*, java.util.*" %>
<%@ page import="org.jfree.chart.*" %>
<%@ page import="org.jfree.chart.axis.*" %>
<%@ page import="org.jfree.chart.labels.StandardCategoryItemLabelGenerator" %>
<%@ page import="org.jfree.chart.plot.*" %>
<%@ page import="org.jfree.chart.renderer.*" %>
<%@ page import="org.jfree.chart.servlet.ServletUtilities" %>
<%@ page import="org.jfree.data.DefaultCategoryDataset" %>
<%@ page import="org.jfree.ui.TextAnchor" %>

<%
//The data for the bar chart

double[] data =
{85, 156, 179.5, 211, 123};
//The labels for the bar chart

String[] labels =
{"Mon", "Tue", "Wed", "Thu", "Fri"};
DefaultCategoryDataset dataset = new DefaultCategoryDataset();

for (int i = 0; i < data.length; i++)
{
dataset.addValue(data[i], null, labels[i]);
}
JFreeChart chart = ChartFactory.createBarChart3D("Weekly Server Load", "Work Week 25", "MBytes", dataset, PlotOrientation.VERTICAL, false, false, false);
chart.setBackgroundPaint(new Color(0xE1E1E1));
CategoryPlot plot = chart.getCategoryPlot();
// 設(shè)置Y軸顯示整數(shù)
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
CategoryAxis domainAxis = plot.getDomainAxis();
//設(shè)置距離圖片左端距離
domainAxis.setLowerMargin(0.05);
BarRenderer3D renderer = new BarRenderer3D();
//設(shè)置柱的顏色
renderer.setSeriesPaint(0, new Color(0xff00));
plot.setRenderer(renderer);
String filename = ServletUtilities.saveChartAsPNG(chart, 300, 280, null, session);
String graphURL = request.getContextPath() + "/displayChart?filename=" + filename;
%>
<html>
<body topmargin="5" leftmargin="5" rightmargin="0">
<div style="font-size:18pt; font-family:verdana; font-weight:bold">
3D Bar Chart
</div>
<br>
<img src="<%= graphURL %>" border=0>
</body>
</html>

畫(huà)出來(lái)的圖:

和ChartDirector畫(huà)出來(lái)的圖做一個(gè)比較:

以前一直是用JFreeChart畫(huà)統(tǒng)計(jì)圖的,不過(guò)JFreeChart畫(huà)出來(lái)的圖形不夠精細(xì),看起來(lái)有些模糊,今天在網(wǎng)上看到另外一個(gè)工具ChartDirector,這是一個(gè)商業(yè)版本的工具,不過(guò)也可以免費(fèi)使用,只是在畫(huà)出來(lái)的圖形下面都有一條它的廣告條。
下面是它的一個(gè)柱狀圖的例子:

范例程序:
<%@page import="ChartDirector.*" %>
<%
//The data for the bar chart

double[] data =
{85, 156, 179.5, 211, 123};

//The labels for the bar chart

String[] labels =
{"Mon", "Tue", "Wed", "Thu", "Fri"};

//Create a XYChart object of size 300 x 280 pixels
XYChart c = new XYChart(300, 280);

//Set the plotarea at (45, 30) and of size 200 x 200 pixels
c.setPlotArea(45, 30, 200, 200);

//Add a title to the chart
c.addTitle("Weekly Server Load");

//Add a title to the y axis
c.yAxis().setTitle("MBytes");

//Add a title to the x axis
c.xAxis().setTitle("Work Week 25");

//Add a bar chart layer with green (0x00ff00) bars using the given data
c.addBarLayer(data, 0xff00).set3D();

//Set the labels on the x axis.
c.xAxis().setLabels(labels);

//output the chart
String chart1URL = c.makeSession(request, "chart1");

//include tool tip for the chart
String imageMap1 = c.getHTMLImageMap("", "", "title='{xLabel}: {value} MBytes'")
;
%>
<html>
<body topmargin="5" leftmargin="5" rightmargin="0">
<div style="font-size:18pt; font-family:verdana; font-weight:bold">
3D Bar Chart
</div>
<hr color="#000080">
<a href="viewsource.jsp?file=<%=request.getServletPath()%>">
<font size="2" face="Verdana">View Chart Source Code</font>
</a>
</div>
<br>
<img src='<%=response.encodeURL("getchart.jsp?"+chart1URL)%>'
usemap="#map1" border="0">
<map name="map1"><%=imageMap1%></map>
</body>
</html>

如果要在柱的頂部顯示數(shù)值,可以調(diào)用Layer的setDataLabelFormat方法設(shè)置,范例:layer.setDataLabelFormat("{value}");
其它的例子可以參考它的文檔的說(shuō)明。ChartDirector的網(wǎng)址:http://www.advsofteng.com
如果要在程序中定時(shí)執(zhí)行任務(wù),可以使用java.util.Timer這個(gè)類(lèi)實(shí)現(xiàn)。使用Timer類(lèi)需要一個(gè)繼承了java.util.TimerTask的類(lèi)。TimerTask是一個(gè)虛類(lèi),需要實(shí)現(xiàn)它的run方法,實(shí)際上是他implements了Runnable接口,而把run方法留給子類(lèi)實(shí)現(xiàn)。
下面是我的一個(gè)例子:

class Worker extends TimerTask
{

public void run()
{
System.out.println("我在工作啦!");
}
} Timer類(lèi)用schedule方法或者scheduleAtFixedRate方法啟動(dòng)定時(shí)執(zhí)行,schedule重載了四個(gè)版本,scheduleAtFixedRate重載了兩個(gè)。每個(gè)方法的實(shí)現(xiàn)都不同,下面是每個(gè)方法的說(shuō)明:
schedule
public void schedule(TimerTask task,
long delay)
- Schedules the specified task for execution after the specified delay.
-
- Parameters:
task
- task to be scheduled.
delay
- delay in milliseconds before task is to be executed.
- Throws:
IllegalArgumentException
- if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException
- if task was already scheduled or cancelled, or timer was cancelled.
說(shuō)明:該方法會(huì)在設(shè)定的延時(shí)后執(zhí)行一次任務(wù)。
schedule
public void schedule(TimerTask task,
Date time)
- Schedules the specified task for execution at the specified time. If the time is in the past, the task is scheduled for immediate execution.
-
- Parameters:
task
- task to be scheduled.
time
- time at which task is to be executed.
- Throws:
IllegalArgumentException
- if time.getTime() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說(shuō)明:該方法會(huì)在指定的時(shí)間點(diǎn)執(zhí)行一次任務(wù)。
schedule
public void schedule(TimerTask task,
long delay,
long period)
- Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals separated by the specified period.
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-delay execution is appropriate for recurring activities that require "smoothness." In other words, it is appropriate for activities where it is more important to keep the frequency accurate in the short run than in the long run. This includes most animation tasks, such as blinking a cursor at regular intervals. It also includes tasks wherein regular activity is performed in response to human input, such as automatically repeating a character as long as a key is held down.
-
- Parameters:
task
- task to be scheduled.
delay
- delay in milliseconds before task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說(shuō)明:該方法會(huì)在指定的延時(shí)后執(zhí)行任務(wù),并且在設(shè)定的周期定時(shí)執(zhí)行任務(wù)。
schedule
public void schedule(TimerTask task,
Date firstTime,
long period)
- Schedules the specified task for repeated fixed-delay execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period.
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-delay execution is appropriate for recurring activities that require "smoothness." In other words, it is appropriate for activities where it is more important to keep the frequency accurate in the short run than in the long run. This includes most animation tasks, such as blinking a cursor at regular intervals. It also includes tasks wherein regular activity is performed in response to human input, such as automatically repeating a character as long as a key is held down.
-
- Parameters:
task
- task to be scheduled.
firstTime
- First time at which task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if time.getTime() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說(shuō)明:該方法會(huì)在指定的時(shí)間點(diǎn)執(zhí)行任務(wù),然后從該時(shí)間點(diǎn)開(kāi)始,在設(shè)定的周期定時(shí)執(zhí)行任務(wù)。特別的,如果設(shè)定的時(shí)間點(diǎn)在當(dāng)前時(shí)間之前,任務(wù)會(huì)被馬上執(zhí)行,然后開(kāi)始按照設(shè)定的周期定時(shí)執(zhí)行任務(wù)。
scheduleAtFixedRate
public void scheduleAtFixedRate(TimerTask task,
long delay,
long period)
- Schedules the specified task for repeated fixed-rate execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals, separated by the specified period.
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-rate execution is appropriate for recurring activities that are sensitive to absolute time, such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time. It is also appropriate for recurring activities where the total time to perform a fixed number of executions is important, such as a countdown timer that ticks once every second for ten seconds. Finally, fixed-rate execution is appropriate for scheduling multiple repeating timer tasks that must remain synchronized with respect to one another.
-
- Parameters:
task
- task to be scheduled.
delay
- delay in milliseconds before task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說(shuō)明:該方法和schedule的相同參數(shù)的版本類(lèi)似,不同的是,如果該任務(wù)因?yàn)槟承┰颍ɡ缋占┒舆t執(zhí)行,那么接下來(lái)的任務(wù)會(huì)盡可能的快速執(zhí)行,以趕上特定的時(shí)間點(diǎn)。
scheduleAtFixedRate
public void scheduleAtFixedRate(TimerTask task,
Date firstTime,
long period)
- Schedules the specified task for repeated fixed-rate execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period.
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-rate execution is appropriate for recurring activities that are sensitive to absolute time, such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time. It is also appropriate for recurring activities where the total time to perform a fixed number of executions is important, such as a countdown timer that ticks once every second for ten seconds. Finally, fixed-rate execution is appropriate for scheduling multiple repeating timer tasks that must remain synchronized with respect to one another.
-
- Parameters:
task
- task to be scheduled.
firstTime
- First time at which task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if time.getTime() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說(shuō)明:和上一個(gè)方法類(lèi)似。
下面是我的一個(gè)測(cè)試片斷:

public static void main(String[] args) throws Exception
{
Timer timer = new Timer(false);
timer.schedule(new Worker(), new Date(System.currentTimeMillis() + 1000));
}
今天得知,現(xiàn)在住的房子,公司要準(zhǔn)備拍賣(mài)了,那就是說(shuō),我又要搬家了。
這將是我大學(xué)畢業(yè)后的第四次搬家了,每年搬一次家,有時(shí)候真的厭倦了這樣的生活,剛適應(yīng)一個(gè)環(huán)境,又要重新去適應(yīng)新的環(huán)境。好想擁有自己的房子,但是現(xiàn)在深圳的房?jī)r(jià)卻讓人望樓興嘆!
什么時(shí)候才能夠讓老百姓過(guò)上安居樂(lè)業(yè)的生活。
《我想有個(gè)家》,潘美辰的這首老歌,現(xiàn)在最能夠代表我的心情了。
Criteria Query是很好的一種面向?qū)ο蟮牟樵?xún)實(shí)現(xiàn),它提供了一種示例查詢(xún)的方式。該方式根據(jù)已有的對(duì)象,查找數(shù)據(jù)庫(kù)中屬性匹配的其他對(duì)象。
下面是一個(gè)場(chǎng)景片斷,模糊查找數(shù)據(jù)庫(kù)中用戶(hù)帳號(hào)為'test',郵件地址為
'georgehill@21cn.com'的實(shí)例,忽略大小寫(xiě)。

public void testCriteriaExampleQuery() throws Exception
{
User user = new User();
user.setAccount("test");
user.setEmail("georgehill@21cn.com");
Criteria criteria = session.createCriteria(User.class).add(Example.create(user).enableLike(MatchMode.ANYWHERE).ignoreCase());
List list = criteria.list();

if (list != null)
{

for (int i = 0; i < list.size(); i++)
{
System.out.println(((User) list.get(i)).getAccount());
}
}
} 示例查詢(xún)需要生成Example實(shí)例,可以通過(guò)Example的靜態(tài)方法create生成。Example類(lèi)有下面的幾個(gè)方法指定查詢(xún)的方式:
excludeZeroes
public Example excludeZeroes()
- Exclude zero-valued properties
-
excludeNone
public Example excludeNone()
- Don't exclude null or zero-valued properties
-
enableLike
public Example enableLike(MatchMode matchMode)
- Use the "like" operator for all string-valued properties
-
enableLike
public Example enableLike()
- Use the "like" operator for all string-valued properties
-
ignoreCase
public Example ignoreCase()
- Ignore case for all string-valued properties
-
excludeProperty
public Example excludeProperty(String name)
- Exclude a particular named property
-
當(dāng)用enableLike()方法時(shí),可以通過(guò)MatchMode指定匹配的方式。MatchMode提供了四種匹配的方式:
摘要: 利用JavaMail的API可以快速的實(shí)現(xiàn)發(fā)送郵件的功能。下面是我使用的一個(gè)簡(jiǎn)單的實(shí)例,實(shí)現(xiàn)了簡(jiǎn)單的文本郵件的發(fā)送。
import java.io.*;import java.util.*;import javax.activation.*;import javax.mail.*;...
閱讀全文
好懷念以前可以過(guò)六一兒童節(jié)的時(shí)候,可以放假,學(xué)校還會(huì)組織活動(dòng),每到這天,都可以名正言順的出去玩。呵呵。現(xiàn)在可沒(méi)有六一兒童節(jié)過(guò)了。
上個(gè)月過(guò)了理論考試,昨天終于第一次開(kāi)起了汽車(chē)。呵呵,一開(kāi)始好緊張啊,給師傅狂罵。

有兩次還差點(diǎn)撞到墻。

后來(lái)熟悉了后,就好了很多了。呵呵,第一天學(xué)會(huì)了怎么啟動(dòng),停車(chē),打檔和轉(zhuǎn)方向盤(pán)。上手還是很快滴!

不過(guò),想起要上路,我就感覺(jué)恐怖。
以前在寫(xiě)程序的時(shí)候,碰到需要比較兩個(gè)有可能為null的實(shí)例時(shí),為了避免出現(xiàn)NullPointerException,經(jīng)常用這樣的一段代碼來(lái)比較:
Object obj1 = "abc";
Object obj2 = "cde";
if ((obj1 == null && obj2 == null) || (obj1 != null && obj1.equals(obj2))

|| (obj2 != null && obj2.equals(obj1)))
{
System.out.println("equals");
} 這樣的程序,讀起來(lái)真是挺拗口。我一直沒(méi)有想到什么好的方法解決這個(gè)問(wèn)題,直到今天在看到JDK的AbstractList源碼的equals方法的實(shí)現(xiàn)時(shí),看到這一段:
if (!(o1==null ? o2==null : o1.equals(o2)))
return false; 原來(lái)用三元運(yùn)算符可以很好的解決這個(gè)問(wèn)題,呵呵,我前面的程序可以改寫(xiě)成:
Object obj1 = "abc";
Object obj2 = "cde";
if (obj1 == null ? obj2 == null : obj1.equals(obj2))
System.out.println("equals"); 真是簡(jiǎn)潔多了!
從對(duì)象池中獲取的實(shí)例,因?yàn)椴⒉磺宄揷hannel是否已經(jīng)設(shè)置成正確的狀態(tài),所以在使用時(shí)最好重新設(shè)置一遍。有以下幾點(diǎn)需要注意:
1.在使用阻塞IO時(shí),需要把該channel設(shè)置成阻塞的,即需要調(diào)用SocketChannel.configureBlocking(true);
2.在使用非阻塞IO時(shí),需要把該channel設(shè)置成非阻塞的,即需要調(diào)用SocketChannel.configureBlocking(false);
3.如果該channel注冊(cè)了selector,那么在返回該實(shí)例到對(duì)象池中,需要把注冊(cè)的selector清除,即需要調(diào)用Selector的close方法。
下面是一段應(yīng)用場(chǎng)景的例子:


// 把命令輸出
channel.configureBlocking(true);
PrintWriter writer = new PrintWriter(channel.socket().getOutputStream(), false);
writer.write(command.endsWith("\n") ? command : command + "\n");
writer.flush();

channel.configureBlocking(false);

// 創(chuàng)建Selector
Selector selector = Selector.open();
// 向Selector注冊(cè)我們需要的READ事件
SelectionKey skey = channel.register(selector, SelectionKey.OP_READ);

boolean stop = false;
int n = 0;
int read = 0;
ByteBuffer buffer = ByteBuffer.allocate(1024);

// 輪詢(xún)

while (!stop)
{
// 獲取Selector返回的時(shí)間值
n = selector.select();

// 當(dāng)傳回的值大于0事,讀事件發(fā)生了

if (n > 0)
{
// 處理發(fā)生的事件

}
}

selector.close();