對Java並發編程的幾點思考

來源:互聯網
上載者:User

標籤:

1. Threads 和 Runnables

  所有的現代作業系統都通過進程和線程來支援並發。進程是通常彼此獨立啟動並執行程式的執行個體,比如,如果你啟動了一個Java程式,作業系統產生一個新的進程,與其他程式一起並存執行。在這些進程的內部,我們使用線程並發執行代碼,因此,我們可以最大限度的利用CPU可用的核心(core)。Java從JDK1.0開始執行線程。在開始一個新的線程之前,你必須指定由這個線程執行的代碼,通常稱為task。這可以通過實現Runnable:一個定義了一個無傳回值無參數的run()方法的函數介面,如下面的代碼所示:

Runnable task = () -> {     //JDK 1.8中的 Lambda 運算式    String threadName = Thread.currentThread().getName();    System.out.println("Hello " + threadName);};task.run();Thread thread = new Thread(task);thread.start();System.out.println("Done!");

2. java 線程池的使用

  上面繼承Thread類和實現Runnable介面,可以實現多線程。但是如果並發的線程數量很多,並且每個線程都是執行一個時間很短的任務就結束了,這樣頻繁建立線程就會大大降低系統的效率,因為頻繁建立線程和銷毀線程需要時間。那麼有沒有一種辦法使得線程可以複用,就是執行完一個任務,並不被銷毀,而是可以繼續執行其他的任務?在Java中可以通過線程池來達到這樣的效果。今天我們就來詳細講解一下Java的線程池,首先我們從最核心的ThreadPoolExecutor類中的方法講起,然後再講述它的實現原理,接著給出了它的使用樣本,最後討論了一下如何合理配置線程池的大小。

  Java中的ThreadPoolExecutor類,java..uitl.concurrent.ThreadPoolExecutor類是線程池中最核心的一個類,因此如果要透徹地瞭解Java中的線程池,必須先瞭解這個類。下面我們來看一下ThreadPoolExecutor類的具體實現源碼。

public class ThreadPoolExecutor extends AbstractExecutorService {        public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,            BlockingQueue<Runnable> workQueue);     public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,            BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);     public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,            BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);     public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,        BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);   }

從上面的代碼可以得知,ThreadPoolExecutor繼承了AbstractExecutorService類,並提供了四個構造器,事實上,通過觀察每個構造器的源碼具體實現,發現前面三個構造器都是調用的第四個構造器進行的初始化工作。下面解釋下一下構造器中各個參數的含義: 

  coorPoolSize:核心池的大小,這個參數跟後面講述的線程池的實現原理有非常大的關係。在建立了線程池後,預設情況下,線程池中並沒有任何線程,而是等待有任務到來才建立線程去執行任務,除非調用了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就可以看出,是預建立線程的意思,即在沒有任務到來之前就建立corePoolSize個線程或者一個線程。預設情況下,在建立了線程池後,線程池中的線程數為0,當有任務來之後,就會建立一個線程去執行任務,當線程池中的線程數目達到corePoolSize後,就會把到達的任務放到緩衝隊列當中;maximumPoolSize:線程池最大線程數,這個參數也是一個非常重要的參數,它表示線上程池中最多能建立多少個線程;keepAliveTime:表示線程沒有任務執行時最多保持多久時間會終止。預設情況下,只有當線程池中的線程數大於corePoolSize時,keepAliveTime才會起作用,直到線程池中的線程數不大於corePoolSize,即當線程池中的線程數大於corePoolSize時,如果一個線程閒置時間達到keepAliveTime,則會終止,直到線程池中的線程數不超過corePoolSize。但是如果調用了allowCoreThreadTimeOut(boolean)方法,線上程池中的線程數不大於corePoolSize時,keepAliveTime參數也會起作用,直到線程池中的線程數為0;unit參數:keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:

TimeUnit.DAYS;               //天TimeUnit.HOURS;             //小時TimeUnit.MINUTES;           //分鐘TimeUnit.SECONDS;           //秒TimeUnit.MILLISECONDS;      //毫秒TimeUnit.MICROSECONDS;      //微妙TimeUnit.NANOSECONDS;       //納秒

workQueue:一個阻塞隊列,用來儲存等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,一般來說,這裡的阻塞隊列有以下幾種選擇:

 

對Java並發編程的幾點思考

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.