溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java線程池的構造方法怎么實現

發(fā)布時間:2022-03-30 16:44:43 來源:億速云 閱讀:164 作者:iii 欄目:開發(fā)技術

本篇內容主要講解“Java線程池的構造方法怎么實現”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java線程池的構造方法怎么實現”吧!

一、 前言

為了實現并發(fā)編程,于是就引入了進程這個概念。進程就相當于操作系統的一個任務。多個進程同時執(zhí)行任務,就實現了并發(fā)編程,能夠更快的執(zhí)行。

但是由于進程還不夠輕量,創(chuàng)建一個進程,銷毀一個進程消耗的資源不可忽視。如果進程數量不多的情況下,這些資源消耗是可以接受的,但是如果頻繁的創(chuàng)建、銷毀進程。就是一筆很大的開銷了。

那要怎么辦呢?

為了解決這個問題,人們引入了更輕量的工具——線程。

線程也被稱為輕量級進程。它的創(chuàng)建、銷毀比進程消耗的資源更少。但是如果任務數量很多,多線程也頂不住頻繁的創(chuàng)建、銷毀了呢?這時線程池就出來解決問題了!

二、線程池是什么?

線程池是類似于Java字符串常量池一樣的東西。

使用線程VS不使用線程

  • 當使用一個線程的時候,就直接從池子里取一個線程過來。

  • 當不用一個線程的時候就把這個線程放到池子里

大家都知道找工作的流程大概是這樣的。

  • 投簡歷

  • 筆試

  • 面試

  • offer

當我們到面試完了之后,會有兩種情況。

  • 通過了,公司打電話通知你,給你發(fā)offer

  • 沒通過,而且一般公司也不告訴你自己沒過,而是完全沒通知你沒有過,這是因為公司可能會把你放到他們的"人才貯備池"里了。

假設公司要找50個人,在秋招的時候,給50個人發(fā)了offer。 但是實際上,只有35個人來入職報道了。這時候,剩下的15個人就從人才貯備池里直接撈出15個,直接發(fā)offer。

這時候可能過了一段時間,公司突然打電話通知你,你被錄用了,要不要來?這個操作就相當于一個線程要被使用到了,直接從池子里拿出來用。

這就是用找工作的例子形容了一下線程池大概是什么意思。

三、線程池構造方法ThreadPoolExecutor的構造方法的參數都是啥意思?

在《阿里巴巴java開發(fā)手冊》中指出了線程資源必須通過線程池提供,不允許在應用中自行顯示的創(chuàng)建線程,這樣一方面是線程的創(chuàng)建更加規(guī)范,可以合理控制開辟線程的數量;另一方面線程的細節(jié)管理交給線程池處理,優(yōu)化了資源的開銷。

"ThreadPoolExecutor"這個類是Java標準庫提供的一組類,用來使用線程池。

ThreadPoolExecutor的構造方法有四個。分別含有不同的參數,使用的場景也不同。
我們就以參數最多的構造方法來介紹。

ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor (
int corePoolSize,
int maximumPoolSize ,
long keepAliveTime ,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
 ThreadFactory threadFactory,
 RejectedExecutionHandler handler
 )

Java線程池的構造方法怎么實現

1.corePoolSize 核心線程數

2.maximumPoolSize 最大線程數

對于核心線程數和最大線程數可能不是很理解到底是干嘛的,這里舉一個員工上班的例子。

核心線程數,就是公司里的正式員工,允許他們可以摸魚一會。 被發(fā)現了不至于開除。(相當于線程池中的線程就算什么也不干也不會被銷毀)

最大線程數,就是公司里的正式員工+臨時工組成的數量,但是這里的臨時工摸魚到了一定時間了就要被開除。(相當于線程池中的線程被銷毀)

3.keepAliveTime 描述臨時工能摸魚多長時間的

4.unit 是一個時間單位,也就是keepAliveTime的單位。

5.workQueue 阻塞隊列,就組織了線程池要執(zhí)行的任務

6.threadFactory 線程的創(chuàng)建方式,通過這個參數來設定不同線程的創(chuàng)建方式

7.RejectedExecutionHandler handler 拒絕策略。當任務隊列滿了的時候,新任務又來了,這時候咋辦?

(1):最新的任務不要了

(2):最老的任務不要了

(3):阻塞等待

(4)開擺:拋出異常

由于ThreadPoolExecutor使用起來比較復雜,最多有7個參數。標準庫為此又為程序員們提供了一組其他的類。相當于對ThreadPoolExecutor又進行了一層封裝。

1.newFixedThreadPool:創(chuàng)建出一個固定線程數量的線程池。

 ExecutorService Service1   =  Executors.newFixedThreadPool (20);

2.newCachedThreadPool:創(chuàng)建出一個數量可變的線程池

ExecutorService Service2   = Executors.newCachedThreadPool ();

3.newSingleThreadExecutor:創(chuàng)建只有一個線程的線程池

ExecutorService Service3  = Executors.newSingleThreadExecutor ();

4.newScheduledThreadPool:創(chuàng)建一個能設定延時時間的線程池。

ExecutorService Service4   = Executors.newScheduledThreadPool (20);

四、模擬實現一個線程池

模擬實現一個線程池的核心操作:
.:將任務加到線程池中--submit。
.:使用Worker類描述一個工作線程,Runnable來描述一個任務。
.:創(chuàng)建一個BlockingQueue阻塞隊列組織所有任務。
.:每個Worker要做的事情就是不停的從阻塞隊列里獲取任務并執(zhí)行。
.:指定線程池中的線程最大數目,如果超過這個數目就不要再繼續(xù)創(chuàng)建線程了。

代碼實現:

我們創(chuàng)建一個線程池并讓它不停的創(chuàng)建進程打印hello

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Created with IntelliJ IDEA.
 *
 
 * @Description: 模擬實現線程池的使用
 */
public class ThreadDemo0327_2 {
    public static void main (String[] args) throws IOException, InterruptedException {
        ThreadPoll threadPoll=new ThreadPoll ();
        for (int i = 0 ; i <10  ; i++) {
            threadPoll.submit (new Runnable () {
                @Override
                public void run () {
                    System.out.println ("hello");
                }
            });
        }
    }
}

class  Worker extends  Thread{
    public   BlockingQueue<Runnable> queue=null;
    public Worker(BlockingQueue<Runnable> queue){
        this.queue=queue;
    }

    @Override
    public void run () {
        //工作線程的具體邏輯
        //需要從阻塞隊列中取任務.
        while (true){
            try {
                Runnable command=queue.take ();
                //通過run來執(zhí)行具體任務
                command.run ();
            }catch (InterruptedException e){
                e.printStackTrace ();
            }
        }
    }
}

class  ThreadPoll{
    //包含一個阻塞隊列,用來組織任務
  public   BlockingQueue<Runnable> queue=new LinkedBlockingQueue<> ();

    //這個list就用來存放當前的工作線程.
    public  List<Thread> works=new ArrayList<> ();

    public  int MAX_WORKER_COUNT=10;

    //通過這個方法,把任務加入到線程池中
    //submit不光可以把任務放到阻塞隊列中,也可以負責創(chuàng)建線程
    public  void submit(Runnable command) throws IOException, InterruptedException {
        if(works.size ()<MAX_WORKER_COUNT){
            //如果當前工作線程的數量不足線程數目上線,就創(chuàng)建出新的線程
            //工作線程就專門找一個類完成
            //worker內部要哦能夠取到隊列的內容,就要把這個隊列實例通過worker的構造方法傳過去
            Worker worker=new Worker (queue);
            worker.start ();
            works.add (worker);
        }
        queue.put (command);
    }
}

運行效果:

可以看到,打印了10個hello。

Java線程池的構造方法怎么實現

到此,相信大家對“Java線程池的構造方法怎么實現”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI