1. 程式人生 > >Java自定義執行緒池和執行緒總數控制

Java自定義執行緒池和執行緒總數控制

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();
			}
		});
	}

	@Override
	public void shutAlldown() {
		for (Worker worker : workers) {
			worker.shutdown();
		}
	}

	@Override
	public void execute(Job job) {
		synchronized (tasks) {
			// 提交任務就是將任務物件加入任務佇列,等待工作執行緒去處理
			tasks.addLast(job);
			tasks.notifyAll();
		}
	}

	@Override
	public void addWorkers(int addNum) {
		// 新執行緒數必須大於零,並且執行緒總數不能大於最大執行緒數
		if ((workers.size() + addNum) <= MAX_SIZE && addNum > 0) {
			initWokers(addNum);
		} else {
			System.out.println("addNum too large");
		}
	}

	@Override
	public 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;

		@Override
		public 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() {
			@Override
			public 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() {
			@Override
			public void run() {
				System.out.println("====2 test====");
			}
		});
	}
}
4 控制執行緒總數
希望在專案中所有的執行緒呼叫,都共用1個固定工作者數大小的執行緒池
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
import com.xy.pool.XYThreadPool;

/**
 * 統一執行緒池管理類 
 */
@Component
public class XYThreadManager {

	private XYThreadPool<Runnable> executorPool;

	@PostConstruct
	public 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 {
	
	@Autowired
	private XYThreadManager threadManager;
	
	public void test() {
		threadManager.getExecutorPool().execute(new Runnable() {
			@Override
			public void run() {
				System.out.println("====3 test====");
			}
		});
	}
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("testService4")
public class TestService4 {
	
	@Autowired
	private XYThreadManager threadManager;
	
	public void test() {
		threadManager.getExecutorPool().execute(new Runnable() {
			@Override
			public 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();
	}

}

相關推薦

Java定義執行執行總數控制

1 概述池化是常見的思想,執行緒池是非常典型的池化的實現,《Java併發程式設計實戰》也大篇幅去講解了Java中的執行緒池。本文實現一個簡單的執行緒池。 2 核心類 【1】介面定義 public interface IThreadPool<Job extends

Java使用執行執行工廠

package com.uno.thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.u

執行執行相關類

執行緒池概述 系統啟用一個新執行緒的成本是比較高的,因為它涉及與作業系統互動。在這種情形下,使用執行緒池可以很好的提高效能。執行緒池在系統啟動時即建立大量空閒的執行緒,程式將一個Runnable物件或Callable物件傳給執行緒池,執行緒池會啟動一個執行緒來執行它們的run()或call方

Java定義類加載ClassPath類加載器

訪問 pub 需要 委派 iat 定義 pro logs repl 1 自定義類加載器: 實現規則: 自定義類加載器,需要重寫findClass,然後通過調用loadClass進行類加載(loadClass通過遞歸實現類的雙親委派加載) package com.daxin

Java 定義線程

dfa and hand blank epo cte 方法的參數 factor handler Java 自定義線程池 https://www.cnblogs.com/yaoxiaowen/p/6576898.html public ThreadPoolExecutor(i

java定義異常以及throwthrows關鍵字

java中內建了很多可能在程式設計時出現的大部分異常。除此之外,使用者可以使用一個類繼承Exception類即可繼承自定義類異常。 在程式中自定義類,大體上分為以下幾個步驟: 建立自定義異常類 在方法中通過throw關鍵字丟擲異常物件。 如果在當前丟擲異常的方法中處理異常,

JAVA定義註解的使用定義

 最近有所瞭解到自定義註解的應用,因此學習了一下,在專案後臺介面開發中,資料的傳輸經常有對資料內容格式及一些資訊規則的校驗,應用註解在資料進入後臺的開始使用自定義註解是一種比較可靠的方案。 一、註解的概念及分類        1.首先我們來看一下什麼是註解:        

經典的java定義資料庫連線程式碼

import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.Driver; import java.sql.DriverManager; import j

android定義下拉重新整理上拉載入控制元件

import android.content.Context; import android.graphics.Point; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.NestedScro

java定義模擬執行

java 執行緒池API提供了newCachedThreadPool() newFixedThreadPool(int) 等方法 1 public static ExecutorService newCachedThreadPool() { 2 return

-1-5 java執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖 sleep()wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在O

 本文關鍵詞: java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒組 執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖  sleep()和wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在Object類中 多執行緒

java concurrent包執行佇列詳細講解

Java執行緒池使用說明一簡介執行緒的使用在java中佔有極其重要的地位,在jdk1.4極其之前的jdk版本中,關於執行緒池的使用是極其簡陋的。在jdk1.5之後這一情況有了很大的改觀。Jdk1.5之後加入了java.util.concurrent包,這個包中主要介紹java

java定義執行--ThreadPoolExecutors

public class MyThreadPool { public static void main(String[] args) { /** * 1.在使用有界佇列的時候:若有新的任務需要執行,如果執行緒池實際執行緒數小於corePoolSize核心執行緒數的時候,則優先建立執行緒。

Executors提供的四種執行定義執行

  執行緒池的思想是一種物件池的思想,開放一塊記憶體空間,裡面存放了眾多(未死亡)的執行緒,池中執行緒執行排程由池管理器來處理。當有執行緒任務時,從池中取一個,執行完畢,物件歸還給池。這樣可以避免反覆建立執行緒物件所帶來的效能開銷,節省了系統的資源。 一、固定大小

java執行佇列詳細講解

Java執行緒池使用說明 一簡介 執行緒的使用在java中佔有極其重要的地位,在jdk1.4極其之前的jdk版本中,關於執行緒池的使用是極其簡陋的。在jdk1.5之後這一情況有了很大的改觀。Jdk1.5之後加入了java.util.concurrent包,這個包中主要介紹j

java.jse-執行-執行-java執行佇列詳細講解

Java執行緒池使用說明 一簡介 執行緒的使用在java中佔有極其重要的地位,在jdk1.4極其之前的jdk版本中,關於執行緒池的使用是極其簡陋的。在jdk1.5之後這一情況有了很大的改觀。Jdk1.5之後加入了java.util.concurrent包,這個包中主要介紹

JAVA執行(三) 執行鎖的深度化

 github演示程式碼地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/src/main/java/com/kawa/thread 1.執行緒池  1.1 執行緒池是什麼 Java中的執行緒

Java併發程式設計:4種執行緩衝佇列BlockingQueue

一. 執行緒池簡介 1. 執行緒池的概念:           執行緒池就是首先建立一些執行緒,它們的集合稱為執行緒池。使用執行緒池可以很好地提高效能,執行緒池在系統啟動時即建立大量空閒的執行緒,程式將一個任務傳給執行緒池,執行緒池就會啟動一

Java——多執行基本使用(四) 執行執行的使用,工廠設計模式的使用

1.執行緒組的概述和使用 Java中使用ThreadGroup來表示執行緒組,它可以對一批執行緒進行分類管理,Java允許程式直接對執行緒組進行控制。            &n

java執行資料庫連線[從學習到工作(二)]

背景:前段時間工作需要開發一個socket服務端,在接受到客戶端發過來的報文資訊後解析報文呼叫資料庫程式完成資料檔案的生成再拼湊結果報文反饋給客戶端。由於客戶數比較多,所以用執行緒池和資料庫連線池。        一.執行緒池