少年阿賓

          那些青春的歲月

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

          #

          1、ReentrantLock 擁有Synchronized相同的并發性和內存語義,此外還多了 鎖投票,定時鎖等候和中斷鎖等候
          線程A和B都要獲取對象O的鎖定,假設A獲取了對象O鎖,B將等待A釋放對O的鎖定,
          如果使用 synchronized ,如果A不釋放,B將一直等下去,不能被中斷
          如果 使用ReentrantLock,如果A不釋放,可以使B在等待了足夠長的時間以后,中斷等待,而干別的事情

          ReentrantLock獲取鎖定與三種方式:
          a) lock(), 如果獲取了鎖立即返回,如果別的線程持有鎖,當前線程則一直處于休眠狀態,直到獲取鎖
          b) tryLock(), 如果獲取了鎖立即返回true,如果別的線程正持有鎖,立即返回false;
          c)tryLock(long timeout,TimeUnit unit), 如果獲取了鎖定立即返回true,如果別的線程正持有鎖,會等待參數給定的時間,在等待的過程中,如果獲取了鎖定,就返回true,如果等待超時,返回false;
          d) lockInterruptibly:如果獲取了鎖定立即返回,如果沒有獲取鎖定,當前線程處于休眠狀態,直到或者鎖定,或者當前線程被別的線程中斷

          2、synchronized是在JVM層面上實現的,不但可以通過一些監控工具監控synchronized的鎖定,而且在代碼執行時出現異常,JVM會自動釋放鎖定,但是使用Lock則不行,lock是通過代碼實現的,要保證鎖定一定會被釋放,就必須將unLock()放到finally{}中

          3、在資源競爭不是很激烈的情況下,Synchronized的性能要優于ReetrantLock,但是在資源競爭很激烈的情況下,Synchronized的性能會下降幾十倍,但是ReetrantLock的性能能維持常態;
          posted @ 2013-05-23 12:39 abin 閱讀(688) | 評論 (0)編輯 收藏

          MySQL 當記錄不存在時插入,當記錄存在時更新.........具體解決辦法如下:
          1、INSERT INTO… ON DUPLICATE KEY UPDATE
          如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后會導致在一個UNIQUE索引或PRIMARY KEY中出現重復值,則執行舊行UPDATE。
          使用環境:
          例如,如果列a被定義為UNIQUE,并且包含值1,則以下兩個語句具有相同的效果:
          首先建表(先說UNIQUE):
          create table abin1(
          id int not null unique,
          username varchar(100),
          password varchar(100)
          )
          insert into abin1 (id,username,password) values (1,'abin1','varyall1') on duplicate key update username='abin12',password='varyall12';

          其次再說主鍵(primary key)類型的:
          create table abin2(
          id int not null,
          username varchar(100),
          password varchar(100),
          constraint pk_abin2 primary key(id)
          )
          執行語句:
          insert into abin2 (id,username,password) values (1,'abin1','varyall1') on duplicate key update username='abin12',password='varyall12';




          2、插入單行記錄:如果不存在插入記錄,如果存在記錄的話,就不再插入
          insert into abin2 (id,username,password) select 1,'abin12','varyall12' from dual
          where not exists (select k.* from abin2 k where k.id=1)


          3、示例一:插入多條記錄

          假設有一個主鍵為 id 的 abin2表,可以使用下面的語句:

          insert into abin2 (id,username,password) select 1,'abin12','varyall12' from dual
          where not exists (select k.* from abin2 k where k.id=1)

          4、
          我們在使用數據庫時可能會經常遇到這種情況。如果一個表在一個字段上建立了唯一索引,當我們再向這個表中使用已經存在的鍵值插入一條記錄,那將會拋出一個主鍵沖突的
          錯誤。當然,我們可能想用新記錄的值來覆蓋原來的記錄值。如果使用傳統的做法,必須先使用DELETE語句刪除原先的記錄,然后再使用INSERT插入新的記錄。而在MySQL中為
          我們提供了一種新的解決方案,這就是REPLACE語句。使用REPLACE插入一條記錄時,如果不重復,REPLACE就和INSERT的功能一樣,如果有重復記錄,REPLACE就使用新記錄的值
          來替換原來的記錄值。

          具體用法:
          replace into abin2 (id,username,password) values (2,'abin','varyall')




          http://blog.csdn.net/kesaihao862/article/details/6718443

          posted @ 2013-05-14 11:14 abin 閱讀(541) | 評論 (0)編輯 收藏

              1)ArrayBlockingQueue:規定大小的BlockingQueue,其構造函數必須帶一個int參數來指明其大小.其所含的對象是以FIFO(先入先出)順序排序的.

                  2)LinkedBlockingQueue:大小不定的BlockingQueue,若其構造函數帶一個規定大小的參數,生成的BlockingQueue有大小限制,若不帶大小參數,所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定.其所含的對象是以FIFO(先入先出)順序排序的

                  3)PriorityBlockingQueue:類似于LinkedBlockQueue,但其所含對象的排序不是FIFO,而是依據對象的自然排序順序或者是構造函數的Comparator決定的順序.

                  4)SynchronousQueue:特殊的BlockingQueue,對其的操作必須是放和取交替完成的,是之前提過的BlockingQueue的又一實現。它給我們提供了在線程之間交換單一元素的極輕量級方法.

              其中LinkedBlockingQueue和ArrayBlockingQueue比較起來,它們背后所用的數據結構不一樣,導致LinkedBlockingQueue的數據吞吐量要大于ArrayBlockingQueue,但在線程數量很大時其性能的可預見性低于ArrayBlockingQueue. 

           http://www.2cto.com/kf/201212/175028.html

          posted @ 2013-05-13 16:54 abin 閱讀(662) | 評論 (1)編輯 收藏

          1.根據ROWID來分
          select * from t_xiaoxi where rowid in(select rid from (select rownum rn,rid from(select rowid rid,cid from

          t_xiaoxi  order by cid desc) where rownum<10000) where rn>9980) order by cid desc;
          執行時間0.03秒
          2.按分析函數來分
          select * from (select t.*,row_number() over(order by cid desc) rk from t_xiaoxi t) where rk<10000 and rk>9980;
          執行時間1.01秒
          3.按ROWNUM來分
          select * from(select t.*,rownum rn from(select * from t_xiaoxi order by cid desc) t where rownum<10000) where

          rn>9980;執行時間0.1秒
          其中t_xiaoxi為表名稱,cid為表的關鍵字段,取按CID降序排序后的第9981-9999條記錄,t_xiaoxi表有70000多條記錄
          個人感覺1的效率最好,3次之,2最差

          posted @ 2013-05-10 13:29 abin 閱讀(479) | 評論 (0)編輯 收藏

          鎖:

          1. 內置鎖 (監視器鎖): 每個java對象都可以做一個實現同步的鎖,這些鎖被成為內置鎖. 獲得鎖的唯一途徑就是進入有這個鎖保護的代碼塊或方法
          2. 重入鎖: 由于內置鎖是可重入的,因此如果某個線程試圖獲得一個以已經由他自己持有的鎖, 那么這個請求就會成功.重入意味著獲取鎖的操作粒度是"線程",而不是"調用"

          volatile 使用條件(必須同時滿足所有條件):

          1. 對變量的寫入操作不依賴變量的當前值,或者你能確保只有單個線程更新變量的值
          2. 該變量不會與其他狀態變量一起納入不變性條件中
          3. 在訪問變量時間不需要加鎖


           


           

          高并發術語



          術語

          英文單詞

          描述

          比較并交換

          Compare and Swap

          CAS操作需要輸入兩個數值,一個舊值(期望操作前的值)和一個新值,在操作期間先比較下舊值有沒有發生變化,如果沒有發生變化,才交換成新值,發生了變化則不交換

          CPU流水線

          CPU pipeline

          CPU流水線的工作方式就象工業生產上的裝配流水線,在CPU中由5~6個不同功能的電路單元組成一條指令處理流水線,然后將一條X86指令分成5~6步后再由這些電路單元分別執行,這樣就能實現在一個CPU時鐘周期完成一條指令,因此提高CPU的運算速度

          內存順序沖突

          Memory order violation

          內存順序沖突一般是由假共享引起,假共享是指多個CPU同時修改同一個緩存行的不同部分而引起其中一個CPU的操作無效,當出現這個內存順序沖突時,CPU必須清空流水線

          共享變量


          在多個線程之間能夠被共享的變量被稱為共享變量。共享變量包括所有的實例變量,靜態變量和數組元素。他們都被存放在堆內存中,Volatile只作用于共享變量。

          內存屏障

          Memory Barriers

          是一組處理器指令,用于實現對內存操作的順序限制。

          緩沖行

          Cache line

          緩存中可以分配的最小存儲單位。處理器填寫緩存線時會加載整個緩存線,需要使用多個主內存讀周期。

          原子操作

          Atomic operations

          不可中斷的一個或一系列操作。

          緩存行填充

          cache line fill

          當處理器識別到從內存中讀取操作數是可緩存的,處理器讀取整個緩存行到適當的緩存(L1,L2,L3的或所有)

          緩存命中

          cache hit

          如果進行高速緩存行填充操作的內存位置仍然是下次處理器訪問的地址時,處理器從緩存中讀取操作數,而不是從內存。

          寫命中

          write hit

          當處理器將操作數寫回到一個內存緩存的區域時,它首先會檢查這個緩存的內存地址是否在緩存行中,如果存在一個有效的緩存行,則處理器將這個操作數寫回到緩存,而不是寫回到內存,這個操作被稱為寫命中。



           

          synchronized

          volatile

          concurrent 

          在并發編程中很常用的實用工具類。此包包括了幾個小的、已標準化的可擴展框架,以及一些提供有用功能的類,沒有這些類,這些功能會很難實現或實現起來冗長乏味。下面簡要描述主要的組件。另請參閱 locks 和 atomic 包。

          執行程序

          接口。Executor 是一個簡單的標準化接口,用于定義類似于線程的自定義子系統,包括線程池、異步 IO 和輕量級任務框架。根據所使用的具體 Executor 類的不同,可能在新創建的線程中,現有的任務執行線程中,或者調用 execute() 的線程中執行任務,并且可能順序或并發執行。ExecutorService 提供了多個完整的異步任務執行框架。ExecutorService 管理任務的排隊和安排,并允許受控制的關閉。ScheduledExecutorService 子接口及相關的接口添加了對延遲的和定期任務執行的支持。ExecutorService 提供了安排異步執行的方法,可執行由 Callable 表示的任何函數,結果類似于 RunnableFuture 返回函數的結果,允許確定執行是否完成,并提供取消執行的方法。RunnableFuture 是擁有 run 方法的 Future,run 方法執行時將設置其結果。

          實現。類 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 提供可調的、靈活的線程池。Executors 類提供大多數 Executor 的常見類型和配置的工廠方法,以及使用它們的幾種實用工具方法。其他基于 Executor 的實用工具包括具體類 FutureTask,它提供 Future 的常見可擴展實現,以及 ExecutorCompletionService,它有助于協調對異步任務組的處理。

          隊列

          java.util.concurrent ConcurrentLinkedQueue 類提供了高效的、可伸縮的、線程安全的非阻塞 FIFO 隊列。java.util.concurrent 中的五個實現都支持擴展的 BlockingQueue 接口,該接口定義了 put 和 take 的阻塞版本:LinkedBlockingQueueArrayBlockingQueueSynchronousQueuePriorityBlockingQueue 和 DelayQueue。這些不同的類覆蓋了生產者-使用者、消息傳遞、并行任務執行和相關并發設計的大多數常見使用的上下文。BlockingDeque 接口擴展 BlockingQueue,以支持 FIFO 和 LIFO(基于堆棧)操作。LinkedBlockingDeque 類提供一個實現。

          計時

          TimeUnit 類為指定和控制基于超時的操作提供了多重粒度(包括納秒級)。該包中的大多數類除了包含不確定的等待之外,還包含基于超時的操作。在使用超時的所有情況中,超時指定了在表明已超時前該方法應該等待的最少時間。在超時發生后,實現會“盡力”檢測超時。但是,在檢測超時與超時之后再次實際執行線程之間可能要經過不確定的時間。接受超時期參數的所有方法將小于等于 0 的值視為根本不會等待。要“永遠”等待,可以使用 Long.MAX_VALUE 值。

          同步器

          四個類可協助實現常見的專用同步語句。Semaphore 是一個經典的并發工具。CountDownLatch 是一個極其簡單但又極其常用的實用工具,用于在保持給定數目的信號、事件或條件前阻塞執行。CyclicBarrier 是一個可重置的多路同步點,在某些并行編程風格中很有用。Exchanger 允許兩個線程在 collection 點交換對象,它在多流水線設計中是有用的。

          并發 Collection

          除隊列外,此包還提供了設計用于多線程上下文中的 Collection 實現:ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetCopyOnWriteArrayList 和 CopyOnWriteArraySet。當期望許多線程訪問一個給定 collection 時,ConcurrentHashMap 通常優于同步的 HashMapConcurrentSkipListMap 通常優于同步的 TreeMap。當期望的讀數和遍歷遠遠大于列表的更新數時,CopyOnWriteArrayList 優于同步的 ArrayList

          此包中與某些類一起使用的“Concurrent&rdquo前綴;是一種簡寫,表明與類似的“同步”類有所不同。例如,java.util.Hashtable 和Collections.synchronizedMap(new HashMap()) 是同步的,但 ConcurrentHashMap 則是“并發的”。并發 collection 是線程安全的,但是不受單個排他鎖的管理。在 ConcurrentHashMap 這一特定情況下,它可以安全地允許進行任意數目的并發讀取,以及數目可調的并發寫入。需要通過單個鎖不允許對 collection 的所有訪問時,“同步”類是很有用的,其代價是較差的可伸縮性。在期望多個線程訪問公共 collection 的其他情況中,通常“并發”版本要更好一些。當 collection 是未共享的,或者僅保持其他鎖時 collection 是可訪問的情況下,非同步 collection 則要更好一些。

          大多數并發 Collection 實現(包括大多數 Queue)與常規的 java.util 約定也不同,因為它們的迭代器提供了弱一致的,而不是快速失敗的遍歷。弱一致的迭代器是線程安全的,但是在迭代時沒有必要凍結 collection,所以它不一定反映自迭代器創建以來的所有更新。

          內存一致性屬性

          Java Language Specification 第 17 章定義了內存操作(如共享變量的讀寫)的 happen-before 關系。只有寫入操作 happen-before 讀取操作時,才保證一個線程寫入的結果對另一個線程的讀取是可視的。synchronized 和 volatile 構造 happen-before 關系,Thread.start() 和Thread.join() 方法形成 happen-before 關系。尤其是:
          • 線程中的每個操作 happen-before 稍后按程序順序傳入的該線程中的每個操作。
          • 一個解除鎖監視器的(synchronized 阻塞或方法退出)happen-before 相同監視器的每個后續鎖(synchronized 阻塞或方法進入)。并且因為 happen-before 關系是可傳遞的,所以解除鎖定之前的線程的所有操作 happen-before 鎖定該監視器的任何線程后續的所有操作。
          • 寫入 volatile 字段 happen-before 每個后續讀取相同字段。volatile 字段的讀取和寫入與進入和退出監視器具有相似的內存一致性效果,但 需要互斥鎖。
          • 在線程上調用 start happen-before 已啟動的線程中的任何線程。
          • 線程中的所有操作 happen-before 從該線程上的 join 成功返回的任何其他線程。
          java.util.concurrent 中所有類的方法及其子包擴展了這些對更高級別同步的保證。尤其是:
          • 線程中將一個對象放入任何并發 collection 之前的操作 happen-before 從另一線程中的 collection 訪問或移除該元素的后續操作。
          • 線程中向 Executor 提交 Runnable 之前的操作 happen-before 其執行開始。同樣適用于向 ExecutorService 提交 Callables
          • 異步計算(由 Future 表示)所采取的操作 happen-before 通過另一線程中 Future.get() 獲取結果后續的操作。
          • “釋放”同步儲存方法(如 Lock.unlockSemaphore.release 和 CountDownLatch.countDown)之前的操作 happen-before 另一線程中相同同步儲存對象成功“獲取”方法(如 Lock.lockSemaphore.acquireCondition.await 和 CountDownLatch.await)的后續操作。
          • 對于通過 Exchanger 成功交換對象的每個線程對,每個線程中 exchange() 之前的操作 happen-before 另一線程中對應 exchange() 后續的操作。
          • 調用 CyclicBarrier.await 之前的操作 happen-before 屏障操作所執行的操作,屏障操作所執行的操作 happen-before 從另一線程中對應await 成功返回的后續操作。

           

          Condition

          Condition 將 Object 監視器方法(waitnotify 和 notifyAll)分解成截然不同的對象,以便通過將這些對象與任意 Lock 實現組合使用,為每個對象提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監視器方法的使用。

          條件(也稱為條件隊列 或條件變量)為線程提供了一個含義,以便在某個狀態條件現在可能為 true 的另一個線程通知它之前,一直掛起該線程(即讓其“等待”)。因為訪問此共享狀態信息發生在不同的線程中,所以它必須受保護,因此要將某種形式的鎖與該條件相關聯。等待提供一個條件的主要屬性是:以原子方式 釋放相關的鎖,并掛起當前線程,就像 Object.wait 做的那樣。

          Condition 實例實質上被綁定到一個鎖上。要為特定 Lock 實例獲得 Condition 實例,請使用其 newCondition() 方法。

          作為一個示例,假定有一個綁定的緩沖區,它支持 put 和 take 方法。如果試圖在空的緩沖區上執行 take 操作,則在某一個項變得可用之前,線程將一直阻塞;如果試圖在滿的緩沖區上執行 put 操作,則在有空間變得可用之前,線程將一直阻塞。我們喜歡在單獨的等待 set 中保存 put 線程和 take 線程,這樣就可以在緩沖區中的項或空間變得可用時利用最佳規劃,一次只通知一個線程。可以使用兩個 Condition 實例來做到這一點。

           class BoundedBuffer {
             final Lock lock = new ReentrantLock();
             final Condition notFull  = lock.newCondition(); 
             final Condition notEmpty = lock.newCondition(); 
          
             final Object[] items = new Object[100];
             int putptr, takeptr, count;
          
             public void put(Object x) throws InterruptedException {
               lock.lock();
               try {
                 while (count == items.length) 
                   notFull.await();
                 items[putptr] = x; 
                 if (++putptr == items.length) putptr = 0;
                 ++count;
                 notEmpty.signal();
               } finally {
                 lock.unlock();
               }
             }
          
             public Object take() throws InterruptedException {
               lock.lock();
               try {
                 while (count == 0) 
                   notEmpty.await();
                 Object x = items[takeptr]; 
                 if (++takeptr == items.length) takeptr = 0;
                 --count;
                 notFull.signal();
                 return x;
               } finally {
                 lock.unlock();
               }
             } 
           }
           
          
          
          ArrayBlockingQueue 類提供了這項功能,因此沒有理由去實現這個示例類。)

          Condition 實現可以提供不同于 Object 監視器方法的行為和語義,比如受保證的通知排序,或者在執行通知時不需要保持一個鎖。如果某個實現提供了這樣特殊的語義,則該實現必須記錄這些語義。

          注意,Condition 實例只是一些普通的對象,它們自身可以用作 synchronized 語句中的目標,并且可以調用自己的 wait 和notification 監視器方法。獲取 Condition 實例的監視器鎖或者使用其監視器方法,與獲取和該 Condition 相關的 Lock 或使用其 waiting 和 signalling 方法沒有什么特定的關系。為了避免混淆,建議除了在其自身的實現中之外,切勿以這種方式使用Condition 實例。

          除非另行說明,否則為任何參數傳遞 null 值將導致拋出 NullPointerException

          實現注意事項

          在等待 Condition 時,允許發生“虛假喚醒”,這通常作為對基礎平臺語義的讓步。對于大多數應用程序,這帶來的實際影響很小,因為 Condition 應該總是在一個循環中被等待,并測試正被等待的狀態聲明。某個實現可以隨意移除可能的虛假喚醒,但建議應用程序程序員總是假定這些虛假喚醒可能發生,因此總是在一個循環中等待。

          三種形式的條件等待(可中斷、不可中斷和超時)在一些平臺上的實現以及它們的性能特征可能會有所不同。尤其是它可能很難提供這些特性和維護特定語義,比如排序保證。更進一步地說,中斷線程實際掛起的能力在所有平臺上并不是總是可行的。

          因此,并不要求某個實現為所有三種形式的等待定義完全相同的保證或語義,也不要求其支持中斷線程的實際掛起。

          要求實現清楚地記錄每個等待方法提供的語義和保證,在某個實現不支持中斷線程的掛起時,它必須遵從此接口中定義的中斷語義。

          由于中斷通常意味著取消,而又通常很少進行中斷檢查,因此實現可以先于普通方法的返回來對中斷進行響應。即使出現在另一個操作后的中斷可能會釋放線程鎖時也是如此。實現應記錄此行為。




          posted @ 2013-05-06 18:33 abin 閱讀(633) | 評論 (1)編輯 收藏

          第一部分:JMOCK測試接口

          package com.abin.lee.mock.jmock;

          /**
           * Created with IntelliJ IDEA.
           * User: abin
           * Date: 13-5-6
           * Time: 下午12:23
           * To change this template use File | Settings | File Templates.
           */
          public interface UserService {
              public String getMessage(String message);
          }





          package com.abin.lee.mock.jmock;

          /**
           * Created with IntelliJ IDEA.
           * User: abin
           * Date: 13-5-6
           * Time: 下午12:24
           * To change this template use File | Settings | File Templates.
           */
          public class UserServiceImpl implements UserService {
              @Override
              public String getMessage(String message) {
                  String result="";
                  result="hello "+message;
                  return result;
              }
          }





          package com.abin.lee.mock.jmock;

          import junit.framework.TestCase;
          import org.jmock.Expectations;
          import org.jmock.Mockery;
          import org.junit.BeforeClass;
          import org.junit.Test;

          /**
           * Created with IntelliJ IDEA.
           * User: abin
           * Date: 13-5-6
           * Time: 下午12:29
           * To change this template use File | Settings | File Templates.
           */
          public class UserManageTest {
              @Test
              public void testUserManage(){
                  Mockery mockery= new Mockery();
                  final UserService userService=mockery.mock(UserService.class);
                  final String message="abin";
                  final String expectValue="hello abin";
                   mockery.checking(new Expectations(){{
                       oneOf(userService).getMessage(message);
                       will(returnValue(expectValue));
                   }});
                  String actual=userService.getMessage(message);
                  System.out.println("actual="+actual);
                  TestCase.assertEquals(expectValue,actual);
                  mockery.assertIsSatisfied();
              }
          }








          第二部分:JMOCK測試普通類

          package com.abin.lee.mock.jmock;

          /**
           * Created with IntelliJ IDEA.
           * User: abin
           * Date: 13-5-6
           * Time: 下午12:43
           * To change this template use File | Settings | File Templates.
           */
          public class UserManage {
              public String getMessage(String message){
                 String result="hello "+message;
                  System.out.println("result="+result);
                  return result;
              }
          }

           






          package com.abin.lee.mock.jmock;

          import junit.framework.TestCase;
          import org.jmock.Expectations;
          import org.jmock.Mockery;
          import org.jmock.integration.junit4.JUnit4Mockery;
          import org.jmock.lib.legacy.ClassImposteriser;
          import org.junit.Test;

          /**
           * Created with IntelliJ IDEA.
           * User: abin
           * Date: 13-5-6
           * Time: 下午12:47
           * To change this template use File | Settings | File Templates.
           */
          public class UserManageTest {
              @Test
              public void testUserManage(){
                  Mockery mockery=new Mockery();
                  mockery.setImposteriser(ClassImposteriser.INSTANCE);
                  final UserManage userManage=mockery.mock(UserManage.class);
                  final String message="abin";
                  final String expectValue="hello abin";
                  mockery.checking(new Expectations(){{
                      oneOf(userManage).getMessage(message);
                      will(returnValue(expectValue));
                  }});
                  String expect=userManage.getMessage(message);
                  System.out.println("expect="+expect);
                  TestCase.assertEquals(expectValue,expect);
                  mockery.assertIsSatisfied();
              }
          }







          posted @ 2013-05-06 12:42 abin 閱讀(611) | 評論 (0)編輯 收藏

          實例一:

          package com.abin.lee.async;

          import org.apache.http.HttpResponse;
          import org.apache.http.client.methods.HttpPost;
          import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
          import org.apache.http.nio.client.HttpAsyncClient;
          import org.apache.http.nio.reactor.IOReactorException;
          import org.junit.Test;

          import java.io.IOException;
          import java.util.concurrent.Future;

          /**
           * Created with IntelliJ IDEA.
           * User: abin
           * Date: 13-4-23
           * Time: 下午6:13
           * To change this template use File | Settings | File Templates.
           */
          public class HttpAsyncClientTest {
              private static final String HttpUrl="http://localhost:8100/MyThread/HttpClientPostProxyServlet";
              @Test
              public void testHttpAsyncClient() throws IOException {
                   HttpAsyncClient httpAsyncClient=new DefaultHttpAsyncClient();
                   httpAsyncClient.start();
                  HttpPost request=null;
                  try {
                      request=new HttpPost(HttpUrl);
                      Future<HttpResponse> future=httpAsyncClient.execute(request,null);
                      HttpResponse response=future.get();
                      System.out.println("response="+response);
                  }catch(Exception e){
                       e.printStackTrace();
                  }finally {
                      if(!request.isAborted()){
                          request.abort();;
                      }
                      httpAsyncClient.getConnectionManager().shutdown();
                  }

              }
          }








          實例二:

          package com.abin.lee.async;

          import org.apache.http.HttpResponse;
          import org.apache.http.client.methods.HttpGet;
          import org.apache.http.client.methods.HttpPost;
          import org.apache.http.concurrent.FutureCallback;
          import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
          import org.apache.http.nio.client.HttpAsyncClient;
          import org.junit.Test;

          import java.io.IOException;
          import java.util.concurrent.CountDownLatch;
          import java.util.concurrent.Future;

          /**
           * Created with IntelliJ IDEA.
           * User: abin
           * Date: 13-4-23
           * Time: 下午6:13
           * To change this template use File | Settings | File Templates.
           */
          public class HttpAsyncClientFutureCallBackTest {
              private static final String HttpUrl="http://localhost:8100/MyThread/HttpClientGetProxyServlet";
              private static final String HttpOneUrl="http://localhost:8100/MyThread/HttpClientGetOneServlet";
              private static final String HttpTwoUrl="http://localhost:8100/MyThread/HttpClientGetTwoServlet";
              @Test
              public void testHttpAsyncClientFutureCallBack() throws IOException {
                   HttpAsyncClient httpAsyncClient=new DefaultHttpAsyncClient();
                   httpAsyncClient.start();
                  HttpGet[] requests=null;
                  try {
                      requests=new HttpGet[]{new HttpGet(HttpUrl),new HttpGet(HttpOneUrl),new HttpGet(HttpTwoUrl)};
                      final CountDownLatch latch=new CountDownLatch(requests.length);
                      for(final HttpGet request:requests){
                          httpAsyncClient.execute(request,new FutureCallback<HttpResponse>() {
                              @Override
                              public void completed(HttpResponse httpResponse) {
                                  latch.countDown();
                                  System.out.println(request.getRequestLine()+"--->"+httpResponse.getStatusLine());
                                  //To change body of implemented methods use File | Settings | File Templates.
                              }

                              @Override
                              public void failed(Exception e) {
                                  latch.countDown();
                                  System.out.println(request.getRequestLine()+"-->"+e.getMessage());
                                  //To change body of implemented methods use File | Settings | File Templates.
                              }

                              @Override
                              public void cancelled() {
                                  latch.countDown();
                                  System.out.println(request.getRequestLine()+"--->"+" cancelled");
                                   //To change body of implemented methods use File | Settings | File Templates.
                              }
                          }) ;
                      }
                      latch.await();
                      System.out.println("shutting down");
                  }catch(Exception e){
                       e.printStackTrace();
                  }finally {
                      httpAsyncClient.getConnectionManager().shutdown();
                  }

              }
          }

          posted @ 2013-04-28 16:26 abin 閱讀(2382) | 評論 (0)編輯 收藏

          在多線程設計中,我猜常常會遇到線程間相互等待以及某個線程等待1個或多個線程的場景,比如多線程精密計算和大量數據處理,這里寫下我自己的體會和理解。

             

              我想應該有很多辦法,如果是簡單的1:1關系,那么可以wait()和notify()解決,就像一把鎖和一把鑰匙;如果是1:N關系,這個1就需要關心N的所有狀態了,最笨的辦法是1可以去查看N當前的狀態,輪詢詢問工作是否做完。而好點的辦法是N做完后主動告訴1,然后N就會有2種選擇,要么聽從1的命令,要么繼續干自己其他的活。

           

              用傳統的方法我想應該是都能實現的,而JDK1.5提供了CyclicBarrier與CountDownLatch來解決了這兩個問題,而她們的區別是:

              CyclicBarrier使所有線程相互等待,而CountDownLatch使一個或多個線程等待其他線程。區別類似上面藍色字體,CountDownLatch不會等待其他線程了,只要做完自己的工作就干自己的活去了,也就是run()方法里其他的任務。

           

          Example:

           

           

          public static void testCountDownLatch() throws InterruptedException{   
            CountDownLatch cdl
          =new CountDownLatch(2);   
            ExecutorService exe
          =Executors.newFixedThreadPool(2);   
             
          class Bow implements  Runnable{   
              CountDownLatch cdl;   
              
          public Bow(CountDownLatch cdl){   
              
          this.cdl=cdl;    
              }
             
              
          public void run(){   
               System.out.println(
          "The bow is coming");   
               System.out.println(
          "kick a bow ");   
               
          this.cdl.countDown();   
               System.out.println(
          "do other thing");   
               }
             
             }
             
            exe.execute(
          new Bow(cdl));   
            exe.execute(
          new Bow(cdl));   
            exe.shutdown();   
            System.out.println(
          "Wait");   
              cdl.await();   
              System.out.println(
          "End..");   
              
           }
             
            
              
          public static void main(String[] args) {   
                  
          try {   
                      Test.testCountDownLatch();   
                  }
           catch (InterruptedException e) {   
                  }
             
              }
            

           

          輸出的結果為:

           

          The bow is coming
          kick a bow
          do other thing
          Wait...
          The bow is coming
          kick a bow
          do other thing
          End..

           

          如上所說do other thing不受影響。

           

          寫了一個CyclicBarrier的例子:

           

          public static void testCyclicBarrier() throws InterruptedException, BrokenBarrierException{
                  CyclicBarrier barr
          =new CyclicBarrier(2+1);
                  
                  ExecutorService exe
          =Executors.newFixedThreadPool(2);
                   
          class Bow implements  Runnable{
                       CyclicBarrier barr;
                          
          public Bow(CyclicBarrier barr){
                          
          this.barr=barr;    
                          }

                          
          public void run(){
                              System.out.println(
          "The bow is coming");
                              System.out.println(
          "kick a down");
                              
          try {
                                  barr.await();
                              }
           catch (InterruptedException e) {
                                  
          // TODO Auto-generated catch block
                                  e.printStackTrace();
                              }
           catch (BrokenBarrierException e) {
                                  
          // TODO Auto-generated catch block
                                  e.printStackTrace();
                              }

                              System.out.println(
          "do other thing");
                              }

                      }

                  exe.execute(
          new Bow(barr));
                  exe.execute(
          new Bow(barr));
                  exe.shutdown();
                  System.out.println(
          "Wait");
                  barr.await();
                 System.out.println(
          "End..");
              
              }



              
          public static void main(String[] args) {
                  
          try {
                      Test.testCyclicBarrier();
                  }
           catch (InterruptedException e) {
                  }

                  
          catch (BrokenBarrierException e) {
                  }

              }

           

          輸出結果為:

           

          Wait...
          The bow is coming
          kick a down
          The bow is coming
          kick a down
          do other thing
          End..
          do other thing

           

          總結:

          我們看到do other thing被阻塞了,直到最后才執行,可見,柵欄和計數器的目完全不同了。向Doug Lea牛人學習:)

           









          在網上看到很多人對于CountDownLatch和CyclicBarrier的區別簡單理解為CountDownLatch是一次性的,而CyclicBarrier在調用reset之后還可以繼續使用。那如果只是這么簡單的話,我覺得CyclicBarrier簡單命名為ResetableCountDownLatch好了,顯然不是的。
          我的理解是,要從他們的設計目的去看這兩個類。javadoc里面的描述是這樣的。

          CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

          CyclicBarrier : A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.

          可能是我的英語不夠好吧, 我感覺從這個javadoc里面要準確理解他們的差異還是不容易的。
          我的理解是

          CountDownLatch : 一個線程(或者多個), 等待另外N個線程完成某個事情之后才能執行。   CyclicBarrier        : N個線程相互等待,任何一個線程完成之前,所有的線程都必須等待。
          這樣應該就清楚一點了,對于CountDownLatch來說,重點是那個“一個線程”, 是它在等待, 而另外那N的線程在把“某個事情”做完之后可以繼續等待,可以終止。而對于CyclicBarrier來說,重點是那N個線程,他們之間任何一個沒有完成,所有的線程都必須等待。



          CountDownLatch 是計數器, 線程完成一個就記一個, 就像 報數一樣, 只不過是遞減的.
          而CyclicBarrier更像一個水閘, 線程執行就想水流, 在水閘處都會堵住, 等到水滿(線程到齊)了, 才開始泄流.

          posted @ 2013-04-28 15:37 abin 閱讀(457) | 評論 (0)編輯 收藏

          查看oracle表結構:
          desc ABIN_LEE;
          select * from user_tab_columns where table_name='ABIN_LEE';
          select dbms_metadata.get_ddl('TABLE','ABIN_LEE') from dual;
          select * from cols where table_name= 'ABIN_LEE';





          posted @ 2013-04-25 14:29 abin 閱讀(451) | 評論 (0)編輯 收藏

          //EasyMockServlet.java
          package com.abin.lee.easymock.servlets;

          import javax.servlet.RequestDispatcher;
          import javax.servlet.ServletContext;
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.io.IOException;

          /**
          * Created with IntelliJ IDEA.
          * User: abin
          * Date: 13-4-22
          * Time: 下午3:12
          * To change this template use File | Settings | File Templates.
          */
          public class EasyMockServlet extends HttpServlet {
              public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
                  System.out.println("doPost come in");
                  String userName=request.getParameter("userName");
                  String passWord=request.getParameter("passWord");
                  System.out.println("userName="+userName+",passWord="+passWord);
                  if("abin".equals(userName)&&"varyall".equals(passWord)){
                      System.out.println("come in");
                      ServletContext context=this.getServletContext();
                      RequestDispatcher dispatcher=context.getNamedDispatcher("dispatcher");
                      dispatcher.forward(request,response);
                  }else{
                      throw new RuntimeException("Login failed.");
                  }
              }

          }





          //EasyMockServletFailedTest.java
          package com.abin.lee.easymock.servlets;

          import org.easymock.EasyMock;
          import org.easymock.IMocksControl;
          import org.junit.Test;

          import javax.servlet.http.HttpServletRequest;

          import static junit.framework.TestCase.assertEquals;
          import static org.junit.Assert.fail;

          /**
          * Created with IntelliJ IDEA.
          * User: abin
          * Date: 13-4-22
          * Time: 下午5:08
          * To change this template use File | Settings | File Templates.
          */
          public class EasyMockServletFailedTest {
              @Test
              public void testEasyMockServletFailed(){
                  HttpServletRequest request=EasyMock.createMock(HttpServletRequest.class);
                  EasyMock.expect(request.getParameter("userName")).andReturn("abin");
                  EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").times(1);
                  EasyMock.replay(request);
                  EasyMockServlet easyMockServlet=new EasyMockServlet();
                  try {
                        easyMockServlet.doPost(request,null);
                        fail("Not caught exception!");
                  }catch(Exception e){
                      assertEquals("Login failed.", e.getMessage());
                      e.printStackTrace();
                  }
                  EasyMock.verify(request);
              }
          }






          //EasyMockServletSuccessTest
          package com.abin.lee.easymock.servlets;

          import org.easymock.EasyMock;
          import org.easymock.IMocksControl;
          import org.junit.Test;

          import javax.servlet.RequestDispatcher;
          import javax.servlet.ServletContext;
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.io.IOException;

          /**
          * Created with IntelliJ IDEA.
          * User: abin
          * Date: 13-4-22
          * Time: 下午7:49
          * To change this template use File | Settings | File Templates.
          */
          public class EasyMockServletSuccessTest {
              @Test
              public void testEasyMockServletSuccess() throws ServletException, IOException {
                  IMocksControl control= EasyMock.createControl();
                  HttpServletRequest request=control.createMock(HttpServletRequest.class);
          //        HttpServletResponse response=control.createMock(HttpServletResponse.class);
                  final ServletContext servletContext=control.createMock(ServletContext.class);
                  RequestDispatcher requestDispatcher=control.createMock(RequestDispatcher.class);

                  EasyMock.expect(request.getParameter("userName")).andReturn("abin").once();
                  EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").once();
                  EasyMock.expect(servletContext.getNamedDispatcher("dispatcher")).andReturn(requestDispatcher).times(1);

                  requestDispatcher.forward(request,null);
                  EasyMock.expectLastCall();

                  control.replay();

                  EasyMockServlet easyMockServlet=new EasyMockServlet(){
                     public ServletContext getServletContext(){
                         return servletContext;
                     }
                  } ;

                  easyMockServlet.doPost(request,null);
                  control.verify();


              }
          }
          posted @ 2013-04-23 13:27 abin 閱讀(756) | 評論 (0)編輯 收藏

          僅列出標題
          共50頁: First 上一頁 12 13 14 15 16 17 18 19 20 下一頁 Last 
          主站蜘蛛池模板: 九江市| 大连市| 高淳县| 东源县| 封丘县| 宁陕县| 扬中市| 高州市| 新疆| 吉首市| 铜川市| 甘谷县| 鄂伦春自治旗| 邯郸县| 闽侯县| 比如县| 大姚县| 奉节县| 武隆县| 苏州市| 盈江县| 荆门市| 河津市| 伊宁市| 莲花县| 西乌| 栾川县| 河间市| 黔江区| 黑山县| 贵州省| 乌鲁木齐市| 甘孜| 桐庐县| 贵溪市| 无为县| 五河县| 罗源县| 苏州市| 文水县| 涿鹿县|