Android 應用性能優化(三) 多核下的多線程計算

    多核的處理器不一樣於單核處理器,能夠同時執行多個線程。能夠說,在理論上雙核的處理器的性能是單核的兩倍,基本上咱們通常不用操心這個設備究竟是多核仍是單核的,由於使用Thread或者AsyTask將工做分派給不一樣線程就足夠了。若是處理器是多核的,那這些線程就會運行在不一樣的核心上,可是可能有的時候要最有效的使用CPU來得到可接受的性能,要特別爲多核定製算法。java

    如下實現作的事情:算法

    1.將原問題劃分紅多個更簡單的子問題緩存

    2.而後將子問題的結果合併處理,算出原問題的解(使用Future和ExcecutorService)安全

    3.成功避免了重複計算不少相同的斐波那契數(使用高併發高吞吐而且線程安全的ConcurrentHashMap做爲緩存)多線程

    代碼以下:併發

private static final int proc = Runtime.getRuntime().availableProcessors();  
   private static final ExecutorService executorService = Executors.newFixedThreadPool(proc + 2);  
  
   public static BigInteger recursiveFasterBigInteger(int n ){  
       if(n>1) {  
           int m = (n/2) + (n&1);  
           BigInteger fM = recursiveFasterBigInteger(m);  
           BigInteger fM_1 = recursiveFasterBigInteger(m-1);  
           //合併結果,計算出原問題的解  
           if((n&1)==1){  
               return fM.pow(2).add(fM_1.pow(2));  
           }else {  
               return fM_1.shiftLeft(1).add(fM).multiply(fM);  
           }  
       }  
       return (n==0)?BigInteger.ZERO:BigInteger.ONE;  
   }  
  
   private static BigInteger recursiveFasterWithCache(int n) {  
       HashMap<Integer, BigInteger> cache = new HashMap<Integer, BigInteger>();  
       return recursiveFasterWithCache(n, cache);  
   }  
  
   private static BigInteger recursiveFasterWithCache(int n, Map<Integer, BigInteger> cache) {  
       if (n > 92) {  
           BigInteger fN = cache.get(n);  
           if (fN == null) {  
               int m = (n / 2) + (n & 1);  
               BigInteger fM = recursiveFasterWithCache(m, cache);  
               BigInteger fM_1 = recursiveFasterWithCache(m - 1, cache);  
               if ((n & 1) == 1) {  
                   fN = fM.pow(2).add(fM_1.pow(2));  
               } else {  
                   fN = fM_1.shiftLeft(1).add(fM).multiply(fM);  
               }  
               cache.put(n, fN);  
           }  
           return fN;  
       }  
       return BigInteger.valueOf(iterativeFaster(n));  
   }  
  
   public static BigInteger recursiveFasterWithCacheAndThread(int n) {  
       int proc = Runtime.getRuntime().availableProcessors();  
       if (n < 128 || proc <= 1) {  
           return recursiveFasterWithCache(n);  
       }  
  
       final ConcurrentHashMap<Integer, BigInteger> cache = new ConcurrentHashMap<Integer, BigInteger>();  
  
       final int m = (n / 2) + (n & 1);  
  
       Callable<BigInteger> callable = new Callable<BigInteger>() {  
           @Override  
           public BigInteger call() throws Exception {  
               return recursiveFasterWithCache(m,cache);  
           }  
       };  
  
       Future<BigInteger> ffM = executorService.submit(callable);  
  
       callable = new Callable<BigInteger>() {  
           @Override  
           public BigInteger call() throws Exception {  
               return recursiveFasterWithCache(m-1,cache);  
           }  
       };  
       Future<BigInteger> ffM_1 = executorService.submit(callable);  
  
       //獲得各部分的結果開始合併  
       BigInteger fM,fM_1,fN;  
  
       try{  
           fM = ffM.get();//獲取第一個子問題的結果(阻塞調用)  
       }catch (Exception e){  
           //若是拋出了異常 那就在當前主線程中計算fM  
           fM = recursiveFasterBigInteger(m);  
       }  
  
       try{  
           fM_1 = ffM_1.get();//獲取第一個子問題的結果(阻塞調用)  
       }catch (Exception e){  
           //若是拋出了異常 那就在當前主線程中計算fM  
           fM = recursiveFasterBigInteger(m-1);  
       }  
  
       if((n & 1) != 0 ){  
           fN = fM.pow(2).add(fM_1.pow(2));  
       }else {  
           fN = fM_1.shiftLeft(1).add(fM).multiply(fM);  
       }  
       return fN;  
   }

    其實不少時候即便把問題分解爲子問題並將子問題分派到不一樣的線程,性能也有可能並無什麼提高,有多是數據之間有依賴,不得不進行同步,線程就可能會花大部分的時間在等待數據。因此實踐中一般是用多線程執行無關的任務,避免同步需求。ide

相關文章
相關標籤/搜索