1. 程式人生 > >多執行緒之Future和Callable【高效能應用場景java.util.concurrent】

多執行緒之Future和Callable【高效能應用場景java.util.concurrent】

業務場景

如查一個數據集合,第一頁至第一百頁,返回總頁數的總結集,然後匯出。

一次需要limit 0 10000,這樣,一個SQL查詢出非常慢。

但用100個執行緒,一個執行緒只查limit0 10 就非常快了,

利用多執行緒的特性,返回多個集合,在順序合併成總集合。

下面是concurrent.Future  例子

           concurrent.Callable

package com.test.thread;

import java.util.ArrayList;  
import java.util.List;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Future;  
  
/**
 *  Future<List<User>>
 *  
 *  應用場景 :1.多執行緒,每個執行緒平均任務耗時一樣
 *          2.需要順序返回的
 *          
 *  順序返回,如多個分頁,但第一頁需要先返回
 *  
 * @author 汪興安
 *
 */
public class ThreadTest {  
  
    /**
     * 定義執行緒池
     */
    public static ExecutorService executos = Executors.newFixedThreadPool(5);  
  
    public static void main(String[] args) {  
        /**
         * 定義集合裝結果集
         */
        List<User> totalList = new ArrayList<User>();  
        
        /**
         * 定義 Future泛型的集合物件,裝多執行緒的,返回資訊
         */
        List<Future<List<User>>> list = new ArrayList<Future<List<User>>>();  
        try {  
            int pageIndex = 0;  
            int maxPage = 6;  
            for (pageIndex = 0; pageIndex < maxPage; pageIndex++) {  
                /**
                 * executos.submit 返回執行緒未來結果
                 */
                Future<List<User>> future = executos.submit(new DemoThread(pageIndex));  
                list.add(future);  
            }  
  
            for (Future<List<User>> dataFuture : list) {  
                //// 獲得第一個任務的結果,如果呼叫get方法,當前執行緒會等待任務執行完畢後才往下執行
                totalList.addAll(dataFuture.get());  //dataFuture.get()  這裡會阻塞   有順序的哦
            }  
            
            //得到分頁後結果總共集合
            for (int i = 0; i < totalList.size(); i++) {
                System.out.println(totalList.get(i).getName());
            }
            
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        
        executos.shutdownNow();
    }  
  
    
    /**
     *  查詢第1頁
        查詢第3頁
        查詢第5頁
        查詢第2頁
        查詢第4頁
        查詢第0頁
        -----結果會順序返回,不用你操心順序問題啦
        anan0
        anan1
        anan2
        anan3
        anan4
        anan5

     */
}  


package com.test.thread;

import java.util.ArrayList;
import java.util.List;  
import java.util.concurrent.Callable;  
  
/**
 * Callable 支援有返回值的多執行緒
 * @author 汪興安
 *
 */
public class DemoThread implements Callable<List<User>> {  
    private int pageIndex;  
  
    /**
     * 通過構造器,初始化
     * @param pageIndex
     */
    public DemoThread(int pageIndex) {  
        this.pageIndex = pageIndex;  
    }  
  
    @Override  
    public List<User> call() throws Exception {  
        //模擬每個執行緒執行耗時不一樣
        if(pageIndex%2==0)
        {
            Thread.sleep(5000);
        }else
        {
            Thread.sleep(2000);
        }
        
        System.out.println("查詢第" + pageIndex + "頁");  
        List<User> list = new ArrayList<User>();  
        
        /**
         * 模擬查詢的資料物件
         */
        User user=new User();
        user.setAge(""+pageIndex);
        user.setName("anan"+pageIndex);
        
        list.add(user);  
        return list;  
    }  
  
}  


===================================華麗分割線=================================================================================

package com.test.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutionException;

/**
 * 
 * @author 汪興安
 * 應用場景 :1.每個執行緒耗時差別大,誰先完成,誰返回
 *           對順序沒有要求。
 * 
 * 
 * 
 * CompletionService 的效能更高。
 * 考慮如下場景:多執行緒下載,結果用Future返回。
 * 第一個檔案特別大,後面的檔案很小。
 * 用方法1,能很快知道已經下載完檔案的結果(不是第一個);
 *
 */
public class CallableAndFuture {
	
	 public static void main(String[] args) {
		  List<User> totalList = new ArrayList<User>();  
		  
	        ExecutorService threadPool = Executors.newCachedThreadPool();
	        CompletionService<List<User>> cs = new ExecutorCompletionService<List<User>>(threadPool);
	        for(int i = 0; i < 6; i++) {
	            cs.submit(new DemoThread(i));
	        }
	        // 可能做一些事情
	        for(int i = 0; i < 6; i++) {
	            try {
	                totalList.addAll(cs.take().get());
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            } catch (ExecutionException e) {
	                e.printStackTrace();
	            }
	        }
	        
	        //得到分頁後結果總共集合
            for (int i = 0; i < totalList.size(); i++) {
            	System.out.println(totalList.get(i).getName());
			}          
	    }
	 /**
	  * 查詢第3頁
		查詢第1頁
		查詢第5頁
		查詢第2頁
		查詢第0頁
		查詢第4頁
		anan5
		anan1
		anan3
		anan2
		anan0
		anan4
	  */

}


總結:兩種方式,應用場景不一樣

         Future<List<User>> future = executos.submit(new DemoThread(pageIndex));   這種可以保證返回的順序  

        CompletionService<List<User>> cs = new ExecutorCompletionService<List<User>>(threadPool);,返回不保證順序,誰先執行完,誰先返回。

        效率上CompletionService更高,實際專案需要根據具體業務需求選擇。

相關推薦

執行FutureCallable高效能應用場景java.util.concurrent

業務場景: 如查一個數據集合,第一頁至第一百頁,返回總頁數的總結集,然後匯出。 一次需要limit 0 10000,這樣,一個SQL查詢出非常慢。 但用100個執行緒,一個執行緒只查limit0 10 就非常快了, 利用多執行緒的特性,返回多個集合,在順序合併成總集合。

java 執行future用法意義

在併發程式設計時,一般使用runnable,然後扔給執行緒池完事,這種情況下不需要執行緒的結果。所以run的返回值是void型別。 如果是一個多執行緒協作程式,比如菲波拉切數列,1,1,2,3,5,8...使用多執行緒來計算。但後者需要前者的結果,就需要用callable介

從零開始學執行取消關閉(六)

小節 為什麼需要取消和關閉: 有時候我們希望在任務或執行緒自然結束之前就停止它們,可能因為使用者取消了操作,或者應用程式需要快速關閉. 取消和關閉的好處: 不會浪費資源執行一些沒用的操作、保證程式的正常退出. Java沒有提供任何機制,來安全地強迫執行緒停止手頭的工作.它提供中斷(執行緒

IOS執行NSoperationGCD的比較

GCD是基於c的底層api,NSOperation屬於object-c類。iOS首先引入的是NSOperation,IOS4之後引入了GCD和NSOperationQueue並且其內部是用gcd實現的。 相對於GCD: 1,NSOperation擁有更多的函式可用,具體檢視api。

執行Future使用詳解

什麼是Future Future是一個未來物件,裡面儲存這執行緒處理結果,它像一個提貨憑證,拿著它你可以隨時去提取結果 什麼時候使用 在兩種情況下,離開Future幾乎很難辦。 一種情況是拆分訂單,比如你的應用收到一個批量訂單,此時如果要求最快的處理訂單,那麼需要併發

執行CountDownLatchCyclicBarrier的區別用法

一.CountDownLatch的使用 CountDownLatch經常用於監聽某些初始化操作,等初始化執行完畢後,再通知主執行緒繼續工作。 CountDownLatch定義: 一個同步輔助類,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。用給定的計數 初

Java執行interrupt()執行終止方式

1. interrupt()說明 在介紹終止執行緒的方式之前,有必要先對interrupt()進行了解。 關於interrupt(),java的djk文件描述如下:http://docs.oracle.com/javase/7/docs/api/ Interrupts this thread

java執行ReentrantLock Condition

ReentrantLock 是JDK中內建鎖,也稱可重入鎖,API也較為簡單。  Condition 可實現 執行緒間通訊,由ReentrantLock 例項產生即 lock.new Condition(); 下面這個demo模擬最簡單的生產者 消費者模式,Add執行緒模

執行startrun

1) start:   用start方法來啟動執行緒,真正實現了多執行緒執行,這時無需等待run方法體程式碼執行完畢而直接繼續執行下面的程式碼。通過呼叫Thread類的start()方法來啟動一個執行緒,這時此執行緒處於就緒(可執行)狀態,並沒有執行,一旦得到c

JAVA執行RunnableThread比較

在我們開發的過程中常常會碰到多執行緒的問題,對於多執行緒的實現方式主要有兩種:實現Runnable介面、繼承Thread類。對於這兩種多執行緒的實現方式也是有著一些差異。既然實現了多執行緒那必然離不開管理這些執行緒,當問題比簡單時一個或者幾個執行緒就OK了,也涉

java執行Future模式使用

Future模式簡述 傳統單執行緒環境下,呼叫函式是同步的,必須等待程式返回結果後,才可進行其他處理。 Futrue模式下,呼叫方式改為非同步。 Futrue模式的核心在於:充分利用主函式中的等待

Java執行 Thread VS Runnable 帶案例

為此,我們舉個例子,假設有火車站有三個視窗,在賣火車票,總共只有5張票。每一個執行緒相當於一個視窗,分別售票 <strong>package com.thread; class my

java執行synchronizedvolatile關鍵字

synchronized同步方法 髒讀 在多個執行緒對同一個物件中的例項變數進行併發訪問的時候,取到的資料可能是被更改過的,稱之為“髒讀”,這就是非執行緒安全的。解決的方法為synchronized關鍵字進行同步,使之操作變成同步而非非同步。 public

JAVA執行Future模式

Future模式有點類似於商品訂單。比如在網購時,當看中某一個商品時,就可以提交訂單,當訂單處理完成後,在家裡等待商品送貨上門即可。或者說更形象的我們傳送Ajax請求的時候,頁面是非同步的進行後臺處理,使用者無需一直等待請求的結果,可繼續瀏覽或操作其他內容。下面看一個例子:1

Java執行CallableFuture介面的實現

Callable和Future     Callable介面定義了一個call方法可以作為執行緒的執行體,但call方法比run方法更強大:     A、call方法可以有返回值     B、call方法可以申明丟擲異常       Callable介面是JDK5後

Java執行Executor框架<CallableFuture、ExecutorExecutorService>

引言 Executor框架是指JDK 1.5中引入的一系列併發庫中與Executor相關的功能類,包括Executor、Exec

Qt執行執行的等待喚醒QWaitCondition

QWatiCondition的成員函式 ·QWaitCondition() ·~QWaitCondition() ·bool wait ( QMutex * mutex, unsigned long time = ULONG_MAX ) ·vo

執行futureTask(future,callable)例項,jdbc資料執行查詢

最近遇到一個這樣的功能要求。在查詢資料時,由於查詢的資料量比較大,一次查詢(一條SQL語句中包含太多的條件)查詢起來很慢,大約要10S左右才能查詢出來,這樣體驗太不好了,需要進行優化。今天想了想,打算採用在後端把一條SQL進行拆分,拆分成為多條SQL語句,再拋給多個執行緒去

Java執行(二)——CallableFutureFutureTask

在上一章節我們介紹了Java實現多執行緒最常用的兩種方式,但是那兩種方式實現執行緒的時候並不能返回執行緒的執行結果。然而有些場景我們需要得到執行緒的執行結果,比如要計算每個部門的這個月的工資,然後進行總計(假設有n個部門,計算每個部門的工資需要花費m個小時,計算

執行IO密集型CPU密集型

CPU密集型(CPU-bound) CPU密集型也叫計算密集型,指的是系統的硬碟、記憶體效能相對CPU要好很多,此時,系統運作大部分的狀況是CPU Loading 100%,CPU要讀/寫I/O(硬碟/記憶體),I/O在很短的時間就可以完成,而CPU還有許多運算要處理,CPU Loading很高