java 多線程

1   Thread,Runnable來操作多線程




----------------------------------------------------------------------------------------------------------------------------------------------------------

2  CountDownLatch(閉鎖)

 JDk1.5提供了一個非常有用的包,Concurrent包,這個包主要用來操作一些併發操作,提供一些併發類,可以方便在項目當中傻瓜式應用。

  JDK1.5以前,使用併發操作,都是通過Thread,Runnable來操作多線程;但是在JDK1.5之後,提供了非常方便的線程池(ThreadExecutorPool),主要代碼由大牛Doug Lea完成,其實是在jdk1.4時代,由於java語言內置對多線程編程的支持比較基礎和有限,所以他寫了這個,因爲實在太過於優秀,所以被加入到jdk之中;

  這次主要對CountDownLatch進行系統的講解

  使用場景:比如對於馬拉松比賽,進行排名計算,參賽者的排名,肯定是跑完比賽之後,進行計算得出的,翻譯成Java識別的預發,就是N個線程執行操作,主線程等到N個子線程執行完畢之後,在繼續往下執行。

      代碼示例

     

複製代碼
 1 public static void testCountDownLatch(){
 2         
 3         int threadCount = 10;
 4         
 5         final CountDownLatch latch = new CountDownLatch(threadCount);
 6         
 7         for(int i=0; i< threadCount; i++){
 8              
 9             new Thread(new Runnable() {
10                 
11                 @Override
12                 public void run() {
13 
14                     System.out.println("線程" + Thread.currentThread().getId() + "開始出發");
15 
16                     try {
17                         Thread.sleep(1000);
18                     } catch (InterruptedException e) {
19                         e.printStackTrace();
20                     }
21 
22                     System.out.println("線程" + Thread.currentThread().getId() + "已到達終點");
23 
24                     latch.countDown();
25                 }
26             }).start();
27         }
28         
29         try {
30             latch.await();
31         } catch (InterruptedException e) {
32             e.printStackTrace();
33         }
34 
35         System.out.println("10個線程已經執行完畢!開始計算排名");
36     }
複製代碼

  執行結果:

複製代碼
線程10開始出發
線程13開始出發
線程12開始出發
線程11開始出發
線程14開始出發
線程15開始出發
線程16開始出發
線程17開始出發
線程18開始出發
線程19開始出發
線程14已到達終點
線程15已到達終點
線程13已到達終點
線程12已到達終點
線程10已到達終點
線程11已到達終點
線程16已到達終點
線程17已到達終點
線程18已到達終點
線程19已到達終點
10個線程已經執行完畢!開始計算排名
複製代碼

  

  源碼分析:

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

    大致意思:也就是說主線程在等待所有其它的子線程完成後再往下執行

    

    2、構造函數:CountDownLatch(int count)//初始化count數目的同步計數器,只有當同步計數器爲0,主線程纔會向下執行
      主要方法:void await()//當前線程等待計數器爲0 
               boolean await(long timeout, TimeUnit unit)//與上面的方法不同,它加了一個時間限制。
              void countDown()//計數器減1
              long getCount()//獲取計數器的值

        3.它的內部有一個輔助的內部類:sync.

       它的實現如下:

     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
     * Synchronization control For CountDownLatch.
     * Uses AQS state to represent count.
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;
 
        Sync(int count) {
            setState(count);
        }
 
        int getCount() {
            return getState();
        }
 
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
 
        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

  4.await()方法的實現
    sync.acquireSharedInterruptibly(1);
     -->if (tryAcquireShared(arg) < 0)//調用3中的tryAcquireShared()方法
            doAcquireSharedInterruptibly(arg);//加入到等待隊列中

  5.countDown()方法的實現
    sync.releaseShared(1);
     --> if (tryReleaseShared(arg))//調用3中的tryReleaseShared()方法
               doReleaseShared();//解鎖

      

參考文章:

           https://my.oschina.net/u/1185331/blog/502350

           http://blog.itpub.net/30024515/viewspace-1432825/


====================================================================================

3 ExecutorService extends Executor  

 ExecutorService executor = Executors.newFixedThreadPool(MAX_POOL_SIZE);
while (iterator.hasNext()) {
LBHostInfoVOMongo mongo = iterator.next();
executor.execute(new Runnable() {
@Override
public void run() {
try {
dao.addLBInfoMonitorResult(mongo, startTime, endTime, time_stamp);
} catch (Exception e) {
logger.error(UTrace.trace(e));
}
}
});
}
executor.shutdown();

    

 ---------------------------------------

ExecutorService(線程池)可以被關閉來拒絕新任務。有兩個不同的方法來關閉。 
shutdown方法 在關閉 ExecutorService 之前等待提交的任務執行完成。 
shutdownNow方法 會阻止開啓新的任務並且嘗試停止當前正在執行的線程,一旦調用該方法,線程池中將沒有激活的任務,沒有等待執行的任務,也沒有新任務提交。 
沒有任務執行的ExecutorService將會被回收。


方法submit擴展了Executor.execute(Runnable) 方法, 創建並返回一個 Future 結果,這個Future可以取消任務的執行或者等待完成得到返回值。 
方法invokeAny and invokeAll 可以執行一組任務,等待至少一個任務或者多個任務完成(ExecutorCompletionService擴展了這些方法的實現)。

===============================================================================

4  executor.submit()

Future<GenericResponse> future = executor.submit(new Callable<GenericResponse>() {
@Override
public GenericResponse call() throws Exception {
return callbackSaveLog(req);
}
}); 


/**
* 負載均衡創建
* @author jz
* @date 2017年9月6日 下午7:49:33
* @param request
* @param response void
*/
@RequestMapping(value = "create")
public void create(HttpServletRequest request, HttpServletResponse response) {
try {
CommonInstanceCreateDTO req = URequest.getObject(request, CommonInstanceCreateDTO.class);
logger.debug(UJson.toString(req));
Future<GenericResponse> future = executor.submit(new Callable<GenericResponse>() {
@Override
public GenericResponse call() throws Exception {
return loadBalanceCreateService.handleCreateArrow(req);
}
});
UResponse.json(future.get(), response);
} catch (Throwable e) {
logger.error(UTrace.trace(e));
UResponse.json(ISmartResponses.SYSTEM_ERROR, response);
}
}

 

<T> Future<T> submit(Callable<T> task);
  • 1

提交一個帶有返回值的任務(Callable),返回值爲Future,表示了任務的執行完成結果,Future.get()方法返回成功執行後的結果。 
如果你想要阻塞當前線程知道執行完成返回結果,那麼你可以這樣做: 
result = exec.submit(aCallable).get();

<T> Future<T> submit(Runnable task, T result);
  • 1

提交一個Runnable任務執行,返回一個Future做爲任務task的代理,Future.get()方法在執行成功後可以返回結果。 
Runnable task 提交的任務 
T results 執行的結果

==================================================================================================



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章