Java自訂線程池和線程總數控制

來源:互聯網
上載者:User
1 概述

池化是常見的思想,線程池是非常典型的池化的實現,《Java並發編程實戰》也大篇幅去講解了Java中的線程池。本文實現一個簡單的線程池。


2 核心類

【1】介面定義

public interface IThreadPool<Job extends Runnable> {/** * 關閉線程池 */public void shutAlldown();/** * 執行任務 *  * @param job 任務 */public void execute(Job job);/** * 添加工作者 *  * @param addNum 添加數 */public void addWorkers(int addNum);/** * 減少工作者 *  * @param reduceNum 減少數目 */public void reduceWorkers(int reduceNum);}
【2】實作類別

線程池的核心是維護了1個工作清單和1個工作者列表。

import java.util.ArrayList;import java.util.Collections;import java.util.LinkedList;import java.util.List;public class XYThreadPool<Job extends Runnable> implements IThreadPool<Job> {// 預設線程數private static int DEAFAULT_SIZE = 5;// 最大線程數private static int MAX_SIZE = 10;// 工作清單private LinkedList<Job> tasks = new LinkedList<Job>();// 背景工作執行緒列表private List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>());/** * 預設建構函式 */public XYThreadPool() {initWokers(DEAFAULT_SIZE);}/** * 執行線程數 *  * @param threadNums 線程數 */public XYThreadPool(int workerNum) {workerNum = workerNum <= 0 ? DEAFAULT_SIZE: workerNum > MAX_SIZE ? MAX_SIZE : workerNum;initWokers(workerNum);}/** * 初始化線程池 *  * @param threadNums 線程數 */public void initWokers(int threadNums) {for (int i = 0; i < threadNums; i++) {Worker worker = new Worker();worker.start();workers.add(worker);}// 添加關閉鉤子Runtime.getRuntime().addShutdownHook(new Thread() {public void run() {shutAlldown();}});}@Overridepublic void shutAlldown() {for (Worker worker : workers) {worker.shutdown();}}@Overridepublic void execute(Job job) {synchronized (tasks) {// 提交任務就是將任務對象加入任務隊列,等待背景工作執行緒去處理tasks.addLast(job);tasks.notifyAll();}}@Overridepublic void addWorkers(int addNum) {// 新線程數必須大於零,並且線程總數不能大於最大線程數if ((workers.size() + addNum) <= MAX_SIZE && addNum > 0) {initWokers(addNum);} else {System.out.println("addNum too large");}}@Overridepublic void reduceWorkers(int reduceNum) {if ((workers.size() - reduceNum <= 0))System.out.println("thread num too small");else {// 暫停指定數量的工作者int count = 0;while (count != reduceNum) {for (Worker w : workers) {w.shutdown();count++;}}}}/** * 背景工作執行緒 */class Worker extends Thread {private volatile boolean flag = true;@Overridepublic void run() {while (flag) {Job job = null;// 加鎖(若只有一個woker可不必加鎖,那就是所謂的單線程的線程池,安全執行緒)synchronized (tasks) {// 任務隊列為空白while (tasks.isEmpty()) {try {// 阻塞,放棄對象鎖,等待被notify喚醒tasks.wait();System.out.println("block when tasks is empty");} catch (InterruptedException e) {e.printStackTrace();}}// 不為空白取出任務job = tasks.removeFirst();System.out.println("get job:" + job + ",do biz");job.run();}}}public void shutdown() {flag = false;}}}

1 當調用wait()方法時線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備


2 Object的方法:void notify(): 喚醒一個正在等待該對象的線程。void notifyAll(): 喚醒所有正在等待該對象的線程。notifyAll使所有原來在該對象上等待被notify的線程統統退出wait狀態,變成等待該對象上的鎖,一旦該對象被解鎖,它們會去競爭。notify只是選擇一個wait狀態線程進行通知,並使它獲得該對象上的鎖,但不驚動其它同樣在等待被該對象notify的線程們,當第一個線程運行完畢以後釋放對象上的鎖,此時如果該對象沒有再次使用notify語句,即便該對象已經空閑,其他wait狀態等待的線程由於沒有得到該對象的通知,繼續處在wait狀態,直到這個對象發出一個notify或notifyAll,它們等待的是被notify或notifyAll,而不是鎖。


3 無需控制線程總數
每調用一次就會建立一個擁有10個線程工作者的線程池。

public class TestService1 {public static void main(String[] args) {// 啟動10個線程XYThreadPool<Runnable> pool = new XYThreadPool<Runnable>(10);pool.execute(new Runnable() {@Overridepublic void run() {System.out.println("====1 test====");}});}}public class TestService2 {public static void main(String[] args) {// 啟動10個線程XYThreadPool<Runnable> pool = new XYThreadPool<Runnable>(10);pool.execute(new Runnable() {@Overridepublic void run() {System.out.println("====2 test====");}});}}


4 控制線程總數
希望在項目中所有的線程調用,都共用1個固定工作者數大小的線程池。

import javax.annotation.PostConstruct;import org.springframework.stereotype.Component;import com.xy.pool.XYThreadPool;/** * 統一線程池管理類  */@Componentpublic class XYThreadManager {private XYThreadPool<Runnable> executorPool;@PostConstructpublic void init() {executorPool = new XYThreadPool<Runnable>(10);}public XYThreadPool<Runnable> getExecutorPool() {return executorPool;}}import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Service("testService3")public class TestService3 {@Autowiredprivate XYThreadManager threadManager;public void test() {threadManager.getExecutorPool().execute(new Runnable() {@Overridepublic void run() {System.out.println("====3 test====");}});}}import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Service("testService4")public class TestService4 {@Autowiredprivate XYThreadManager threadManager;public void test() {threadManager.getExecutorPool().execute(new Runnable() {@Overridepublic void run() {System.out.println("====4 test====");}});}}import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestMain {@SuppressWarnings("resource")public static void main(String[] args) {ApplicationContext atc = new ClassPathXmlApplicationContext("applicationContext.xml");TestService3 t3 = (TestService3) atc.getBean("testService3");t3.test();TestService4 t4 = (TestService4) atc.getBean("testService4");t4.test();}}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.