日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android開發ThreadPoolExecutor與自定義線程池詳解_Android

作者:Coolbreeze ? 更新時間: 2022-12-21 編程語言

概述

1、ThreadPoolExecutor作為java.util.concurrent包對外提供基礎實現,以內部線程池的形式對外提供管理任務執行,線程調度,線程池管理等等服務;

2、Executors方法提供的線程服務,都是通過參數設置來實現不同的線程池機制。

3、先來了解其線程池管理的機制,有助于正確使用,避免錯誤使用導致嚴重故障。同時可以根據自己的需求實現自己的線程池

ThreadPoolExecutor 類

構造方法

public ThreadPoolExecutor(
	int corePoolSize,					//核心線程數量:如果當前運行的線程數量沒有達到 corePoolSize,則新建一個線程,否則加入到任務隊列中
	int maximumPoolSize,				//最大線程數:當前系統最多存在的線程數
	long keepAliveTime,					//最大空閑時間:線程空閑的最大時間,超出時間該線程會銷毀;設置allowCodeThreadTimeOut(true/false),可控制核心線程是否銷毀,默認false 表示允許核心線程即使超過最大線程時間也不會銷毀
	TimeUnit unit,						//時間單位:	線程空閑的最大時間的單位
	BlockingQueue<Runnable> workQueue,	//任務隊列:	核心線程數量滿了之后,提交的任務加入到隊列中,等待核心線程數減少后再去創建線程;當任務隊列已滿,但沒有達到最大線程數時,則新建非核心線程
	ThreadFactory threadFactory,		//線程工廠:	自定義線程的創建
	RejectedExecutionHandler handler	//飽和處理機制:當任務隊列已滿且達到最大線程數時,采取的措施
)	

線程池原理

線程池底層使用**堵塞式隊列 BlockingQueue **。

隊列遵從:先進先出,后進后出原則。 阻塞隊列(BlockingQueue)和非阻塞隊列(ConcurrentLinkedQueue )區別:

無界和有界隊列:

ConcurrentLinkedQueue 是無界隊列,不用設置長度,可以隨便存放值(其實是jdk偽造的,最大長度是Integer的最大值) BlockingQueue 是有界隊列,需要設置長度。 注意:如果BlockingQueue 不設置等待時間就是非阻塞隊列

存入:

非阻塞隊列:如果存放超出了隊列總數,添加不進去,就會丟失。 阻塞隊列:如果存放超出了隊列總數,進行等待,直到有隊列出列,或者超時設置的等待時間)

獲取:

非阻塞隊列:如果為空時,返回空。 阻塞隊列:如果為空時,進行等待,直到有新的隊列入列,或者超過設置的等待時間

創建線程池的構造方法

ThreadPoolExecutor(int corePoolSize,
                   int maximumPoolSize,
                   long keepAliveTime,
                   TimeUnit unit,
                   BlockingQueue<Runnable> workQueue)
  • ThreadPoolExecutor
  • 參數說明
  • 核心線程大小(corePoolSize)
  • 最大線程大小(maximumPoolSize)
  • 終止時間(keepAliveTime)
  • Unit 超時時間
  • workQueue 線程容器

自定義線程池

1、編寫任務類

public class MyTask implements Runnable{
	//任務id
	private int id;
	public MyTask(int id){
	    this.id=id;
	}
	@Override
	public void run() {
	    String name=Thread.currentThread().getName();
	    System.out.println("線程:"+name+"-->即將執行任務"+id);
	    try {
	        Thread.sleep(200);
	    } catch (InterruptedException e) {
	        e.printStackTrace();
	    }
	    System.out.println("線程:"+name+"執行完成"+id);
	}
	@Override
	public String toString() {
	    return "MyTask{" +
	            "id=" + id +
	            '}';
	}
}

2、編寫線程類,用于執行任務

public class MyThread extends  Thread{
    private List<Runnable> tasks;
    public MyThread(String name, List<Runnable> tasks){
        super(name);
        this.tasks=tasks;
    }
    @Override
    public void run() {
        while (tasks.size() > 0){
            Runnable r= tasks.remove(0);
            r.run();
        }
    }
}

3、編寫線程池類,用于管理線程的執行

public class MyThreadPool {
    private List<Runnable>  tasks = Collections.synchronizedList(new LinkedList<>());
    /**
     * 當前線程數
     */
    private int num;
    /**
     * 核心線程數
     */
    private int corePoolSize;
    /**
     * 最大線程數
     */
    private int maxSize;
    /**
     * 任務隊列數
     */
    private int workSize;
    public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
        this.corePoolSize = corePoolSize;
        this.maxSize = maxSize;
        this.workSize = workSize;
    }
    /**
     * 提交任務
     */
    public void submit(Runnable r){
        if (tasks.size()>=workSize && tasks.size() > maxSize){
            System.out.println("任務:"+r+"被丟棄了");
        }else{
            tasks.add(r);
            execTask(r);
        }
    }
    public void execTask(Runnable r){
        if (corePoolSize > num){
            new MyThread("核心線程:"+num,tasks).start();
            num++;
        }else  if(num < maxSize){
            new MyThread("非核心線程:"+num,tasks).start();
            num++;
        }else{
            System.out.println("任務:"+r+"被緩存了");
        }
    }
}

4、測試

public class Demo {
    public static void main(String[] args) {
        MyThreadPool myThreadPool = new MyThreadPool(2, 4, 20);
        for (int i =0;i< 300;i++){
            MyTask myTask = new MyTask(i);
            myThreadPool.submit(myTask);
        }
    }
}

以上就是Android開發中ThreadPoolExecutor與自定義線程池;

文末

1、用ThreadPoolExecutor自定義線程池,看線程是的用途,如果任務量不大,可以用無界隊列,如果任務量非常大,要用有界隊列,防止OOM

2、如果任務量很大,還要求每個任務都處理成功,要對提交的任務進行阻塞提交,重寫拒絕機制,改為阻塞提交。保證不拋棄一個任務

3、最大線程數一般設為2N+1最好,N是CPU核數

4、核心線程數,看應用,如果是任務,一天跑一次,設置為0,合適,因為跑完就停掉了,如果是常用線程池,看任務量,是保留一個核心還是幾個核心線程數

5、如果要獲取任務執行結果,用CompletionService,但是注意,獲取任務的結果的要重新開一個線程獲取,如果在主線程獲取,就要等任務都提交后才獲取,就會阻塞大量任務結果,隊列過大OOM,所以最好異步開個線程獲取結果

原文鏈接:https://juejin.cn/post/7168453723591540743

欄目分類
最近更新