Java併發(三):實例引出併發應用場景

前兩篇介紹了一些Java併發的基礎知識,博主正巧遇到一種需求:查詢數據庫,根據查詢結果集修改數據庫記錄,但整個流程是作成了一個schedule的,而且查詢比較耗時,而且須要每兩分鐘執行一次,cpu常常因等待服務器響應的查詢結果而進入等待,故須要在此基礎上考慮性能優化,sql優化能夠提升一些系統效率,一樣,多線程也能夠...html

下面博主作個DEMO引出一些Java併發的實際應用場景:java

 

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;


public class TestThread implements Runnable{

    private String name;

    private Integer i = 0;

    List list = new ArrayList();

    public TestThread(String name) {
        this.name=name;
        for(int i=0; i<100; i++){
            list.add(i);
        }
    }

    @Override
    public void run() {
        Long past = System.currentTimeMillis();
        get();
        System.out.println(System.currentTimeMillis()-past);
    }
    private void get(){

        while(true){
            try{
                Thread.sleep(200);
            }catch(Exception e){
                e.printStackTrace();
            }
            synchronized (i){
                if(i>=100){
                    break;
                }
                System.out.println(list.get(i++));
            }

        }

    }

    public static void main(String[] args) {
        //線程池方式
        ExecutorService exector = new ThreadPoolExecutor(5, 7, 30,
                TimeUnit.MINUTES, new ArrayBlockingQueue<>(10));
        //對於最大線程數和核心線程數的參考值,對於cpu密集型任務,能夠選擇NCPU+1,對於耗時較長的IO操做,能夠選擇2*NCPU
        TestThread a = new TestThread("A");
        exector.execute(a);
        exector.execute(a);
        exector.execute(a);
        exector.execute(a);
        exector.execute(a);
        exector.execute(a);
        exector.execute(a);
        exector.execute(a);

        //普通方式
        /*TestThread a = new TestThread("A");
        new Thread(a).start();
        new Thread(a).start();
        new Thread(a).start();
        new Thread(a).start();*/
    }
}

TIP:不推薦使用Executors.newFixedThreadPool()來建立線程池,你們看底層代碼:sql

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

newFixedThreadPool()方法底層仍是調用了new ThreadPoolExecutor(),但線程等待隊列(LinkedBlockingQueue)默認是不限定其長度的,意味着有大量線程入隊時,會有內存溢出的風險,推薦你們使用new ThreadPoolExecutor()來建立線程池...數據庫

 

經過以上代碼(能夠跑)感覺獲得單線程和多線程的性能差距,設備越好,cpu核數越多,應該結果越明顯,固然這不是絕對的,有時咱們得考慮多線程的上下文切換的時間佔用率和多線程同步的性能消耗...另外,咱們日常應該使用線程池來管理線程,由於比較方便,JavaAPI也已經將細節實現到位,各位能夠用這樣線程安全的方式結合索引遍歷集合,這樣對於集合內的元素就能夠多線程遍歷並觸發各自的操做,例如更新數據庫等,能夠說很是實用...安全

 

多線程使用的主要目的在於:

一、吞吐量:你作WEB,容器幫你作了多線程,可是他只能幫你作請求層面的。簡單的說,可能就是一個請求一個線程。或多個請求一個線程。若是是單線程,那同時只能處理一個用戶的請求。

二、伸縮性:也就是說,你能夠經過增長CPU核數來提高性能。若是是單線程,那程序執行到死也就利用了單核,確定沒辦法經過增長CPU核數來提高性能。
性能優化

 

參考博文:http://www.cnblogs.com/dolphin0520/p/3932921.html服務器

相關文章
相關標籤/搜索