首頁  >  文章  >  Java  >  Java執行緒池的建構方法怎麼實現

Java執行緒池的建構方法怎麼實現

轉載
2023-04-19 15:13:07729瀏覽

一、前言

為了實現並發編程,於是就引入了進程這個概念。進程就相當於作業系統的一個任務。多個進程同時執行任務,就實現了並發編程,能夠更快的執行。

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

那該怎麼辦?

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

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

二、線程池是什麼?

執行緒池是類似Java字串常數池一樣的東西。

使用執行緒VS不使用執行緒

  • 當使用一個執行緒的時候,就直接從池子裡取一個執行緒過來。

  • 當不用一個執行緒的時候就把這個執行緒放到池子裡

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

  • 投履歷

  • 筆試

  • 面試

  • offer

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

通過了,公司打電話通知你,給你發offer

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

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

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

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

三、執行緒池建構方法ThreadPoolExecutor的建構方法的參數都是啥意思?

在《阿里巴巴java開發手冊》中指出了線程資源必須透過線程池提供,不允許在應用程式中自行顯示的創建線程,這樣一方面是線程的創建更加規範,可以合理控制開闢執行緒的數量;另一方面執行緒的細節管理交給執行緒池處理,優化了資源的開銷。

Java執行緒池的建構方法怎麼實現

"ThreadPoolExecutor"這個類別是Java標準函式庫提供的一組類,用來使用執行緒池。

ThreadPoolExecutor的建構方法有四個。分別含有不同的參數,所使用的場景也不同。

我們就以參數最多的建構方法來介紹。

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

1.corePoolSize 核心執行緒數

2.maximumPoolSize 最大執行緒數

對於核心執行緒數和最大執行緒數可能不是很理解到底是幹嘛的,這裡舉一個員工上班的例子。

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

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

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

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

5.workQueue 阻塞佇列,就組織了執行緒池要執行的任務

#6.threadFactory 執行緒的建立方式,透過這個參數來設定不同執行緒的建立方式

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

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

(3):阻塞等待#( 4)開擺:拋出例外

由於ThreadPoolExecutor使用起來比較複雜,最多有7個參數。標準庫為此又為程式設計師提供了一組其他的類別。相當於ThreadPoolExecutor又進行了一層封裝。

1.newFixedThreadPool:建立出一個固定執行緒數量的執行緒池。

 ExecutorService Service1   =  Executors.newFixedThreadPool (20);

2.newCachedThreadPool:建立出一個數量可變的執行緒池

ExecutorService Service2   = Executors.newCachedThreadPool ();

3.

newSingleThreadExecutor

:建立只有一個執行緒的執行緒池

ExecutorService Service3  = Executors.newSingleThreadExecutor ();
4.

newScheduledThreadPool###:建立一個能設定延時時間的執行緒池。 ###
ExecutorService Service4   = Executors.newScheduledThreadPool (20);
###四、模擬實作一個執行緒池###
模拟实现一个线程池的核心操作:
.:将任务加到线程池中--submit。
.:使用Worker类描述一个工作线程,Runnable来描述一个任务。
.:创建一个BlockingQueue阻塞队列组织所有任务。
.:每个Worker要做的事情就是不停的从阻塞队列里获取任务并执行。
.:指定线程池中的线程最大数目,如果超过这个数目就不要再继续创建线程了。
######程式碼實作:######

我们创建一个线程池并让它不停的创建进程打印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来执行具体任务
                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不光可以把任务放到阻塞队列中,也可以负责创建线程
    public  void submit(Runnable command) throws IOException, InterruptedException {
        if(works.size ()<MAX_WORKER_COUNT){
            //如果当前工作线程的数量不足线程数目上线,就创建出新的线程
            //工作线程就专门找一个类完成
            //worker内部要哦能够取到队列的内容,就要把这个队列实例通过worker的构造方法传过去
            Worker worker=new Worker (queue);
            worker.start ();
            works.add (worker);
        }
        queue.put (command);
    }
}

运行效果:

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

Java執行緒池的建構方法怎麼實現

以上是Java執行緒池的建構方法怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除