【Java ee初階】多線程(7)

一、線程池

線程池的一些參數:

corePoolSize:核心線程數量

maximumPoolSize:核心線程數量+臨時線程數量

上述是“java 的線程池策略”(其他語言,其他庫的線程池可能不同)

keepAliveTime :臨時線程的存活時間.臨時線程允許摸魚的最大時間

Timeunit:時間單位:秒/分鐘/毫秒...

workQueue:線程池要完成的任務隊列,每個任務都是通過Runnable來進行描述的

線程池在使用的時候,首先會創建一些線程,然后需要調用者給線程池放一些任務,這些線程就會從隊列中取出任務,并且執行里面的代碼。

(*工廠設計模式:正常創建一個對象是通過構造方法,new出來的。但是構造方法存在一定缺陷的,工廠模式就用來填補上這樣的缺陷。不用構造方法來出池化對象,通過一組靜態方法來初始化對象,靜態方法就可以起不同的名字來做區分了。)

ThreadFactory:線程工廠 這個類就是Thread類的工廠類,由于在線程池中,是需要創建很多線程的,創建出來的線程需要進行哪些初始化操作?就可以通過threadFactory來進行設定。

實際上就是通過newThread方法,針對Thread對象進行初始化,再把這個Thread對象返回出來。比如想把線程池中的線程,按照一定的規則,設置name,或者想把線程池的線程全都設置成后臺線程,或者都設置xxx為優先級。

例如,我想要將笛卡爾坐標系下的點轉化為極坐標下的點表示,那么——

然而,多個版本的構造方法,需要“重載”,而重載要求方法名稱相同但是參數列表不能相同,這里的參數列表相同,因此無法構成重載。那么此時的解決方法也就是:

這就是用來構造Point對象的類,也被稱為“工廠類”

RejectedExecutionHandler:拒絕策略

線程池,有任務列表、阻塞隊列,當任務隊列滿了的時候,如果再次添加新的任務,會發生什么呢?

正常來說,除非特殊說明,我們寫的代碼是不希望有這種突發性的阻塞的,因為這種阻塞稍不留神可能就對程序造成不可預估的影響。

因此直接讓添加任務的線程阻塞,其實是不太好的,不太好就意味著要有其他的方法——因此標準庫的線程池就引入了“拒絕策略”

正常情況下,是線程池里面的線程執行任務的,但是現在線程池里面的線程忙不過來了,就只能由調用者自己找個線程來執行任務

標準庫中提供了一個對ThreadPoolExecutor進行了封裝的簡化版本Executors,本質上也是工廠類,提供了一些工廠方法,對上述的ThreadPoolExecutor進行不同的初始化。

這里的工廠方法,就是在創建不同風格的線程池。

package Thread;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class demo39 {public static void main(String[] args) {//固定線程數目的線程池,核心線程數和最大線程數都是4ExecutorService executorService = Executors.newFixedThreadPool(4);//核心線程數設置為0,最大線程數設為一個Int最大值這樣的線程池ExecutorService executorService1 = Executors.newCachedThreadPool();//固定只有一個線程的線程池(這個東西確實用的不多,可以通過這種方式來代替創建線程的方式)ExecutorService executorService2 = Executors.newSingleThreadExecutor();//這個線程池,本質上是一個定時器,放到這個線程池中的任務,會在一定時間之后執行ExecutorService executorService3 = Executors.newScheduledThreadPool(4);}}

現在我們來讓這個線程池來執行一些任務,為了更清晰地看出這個任務做了10次,我們來對i進行打印。然而這里不能直接這么些,會出現“變量捕獲”的問題。

這里通過這種方法來進行解決。

有些公司更加想要完全體的ThreadPoolExecutor,可控性更強。

如果隊列中沒有其他的任務,take就會阻塞,一直阻塞到其他線程執行submit為止

package Thread;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;class MyFixedThreadPool{ // 固定線程池。private BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>(); // 阻塞隊列,用于存放任務。public MyFixedThreadPool(int n){ // 構造方法,初始化線程池。for(int i = 0; i < n; i++){ // 創建n個線程。Thread t = new Thread(()->{ // 創建線程。try {while (true) {Runnable task = blockingQueue.take(); // 從阻塞隊列中取出任務。task.run(); // 執行任務。}} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}    });t.start();    }       
}public void submit(Runnable task) throws Exception{ // 提交任務。// 1. 將任務放入阻塞隊列。blockingQueue.put(task);}
}public class demo40 {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubMyFixedThreadPool myFixedThreadPool = new MyFixedThreadPool(100); // 創建線程池。for(int i = 0; i < 10; i++){ // 提交1000個任務。int finalI = i; // 閉包。myFixedThreadPool.submit(()->{ // 提交任務。System.out.println("任務" + finalI + "正在執行"); // 打印任務正在執行。});}}}

二、定時器

定時器在java編程中是一個非常終于熬的組件。

阻塞隊列,太重要了,太常用了,在實際工作中,會把阻塞隊列單獨封裝成一個/一組服務器

定時器也是類似,也會被單獨封裝成一個/一組服務器,類似于鬧鐘。

為什么需要定時器呢?——編程中有些任務,不需要立即執行,而是要等一會兒,等到到一定時間的時候再去執行。

Java標準庫提供了Timer這樣的類,可以通過他來實現簡單的定時器。

一開始輸出:程序啟動,過了4s之后輸出“定時器執行任務”

自行實現一個定時器

package Thread;import java.util.PriorityQueue;class MyTimerTask implements Comparable<MyTimerTask>{private Runnable task;private long delay;private long time ;public MyTimerTask(Runnable task, long delay){this.task = task;this.time = delay + System.currentTimeMillis();}public Runnable getTask(){return task;}public long getTime(){return time;}public int compareTo(MyTimerTask o){ // 比較兩個任務的時間,誰的時間小誰排在前面。return (int)(this.time - o.time); // 比較兩個任務的時間,誰的時間小誰排在前面。} // 比較兩個任務的時間,誰的時間小誰排在前面。
}//自己實現定時器
//定時器能夠同時管理多個任務
//有一定的數據結構來組織這多個任務
//ArrayList不太合適
//更好的選擇是優先級隊列class MyTimer{private PriorityQueue<MyTimerTask> queue = new PriorityQueue<MyTimerTask>();private static Object locker = new Object();public MyTimer(){//創建線程Thread t = new Thread(()->{ // 線程的任務是不斷地從隊列中取出任務,并執行。while (true) {try { // 捕獲異常。synchronized(locker){ // 出隊列。if(queue.isEmpty()){locker.wait();}MyTimerTask task = queue.peek(); // 取出隊列中的第一個任務。long curTime = System.currentTimeMillis(); // 獲取當前時間。if(curTime < task.getTime()){ // 如果當前時間小于任務的時間,說明任務還沒有到執行時間。locker.wait(task.getTime() - curTime);}else{queue.poll(); // 取出隊列中的第一個任務。task.getTask().run(); // 執行任務。}}} catch (InterruptedException e) { // 捕獲異常。e.printStackTrace(); // 打印異常棧。}}});t.start(); // 啟動線程。}public void schedule(Runnable task, long delay){ synchronized(locker){ // 入隊列。queue.offer(new MyTimerTask(task, delay)); // 入隊列。locker.notify(); // 喚醒線程。} // 入隊列。}
}public class demo42 {public static void main(String[] args) {MyTimer timer = new MyTimer(); // 創建定時器。timer.schedule(new Runnable() {@Overridepublic void run() { // 任務的執行邏輯。System.out.println("定時任務 3000"); // 打印出 hello world。}}, 3000);timer.schedule(new Runnable() {@Overridepublic void run() { // 任務的執行邏輯。System.out.println("定時任務 2000"); // 打印出 hello world。}}, 2000);        timer.schedule(new Runnable() {@Overridepublic void run() { // 任務的執行邏輯。System.out.println("定時任務 1000"); // 打印出 hello world。}}, 1000);}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81823.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81823.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81823.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux 常用指令詳解

Linux 操作系統中有大量強大的命令行工具&#xff0c;下面我將分類介紹一些最常用的指令及其用法。 ## 文件與目錄操作 ### 1. ls - 列出目錄內容 ls [選項] [目錄名] 常用選項&#xff1a; - -l&#xff1a;長格式顯示&#xff08;詳細信息&#xff09; - -a&#xff1a;顯…

uv安裝及使用

windows安裝參考&#xff1a; 什么是python uv&#xff0c;如何在windows上安裝uv&#xff0c;基礎的用法有哪些&#xff1f;_windows安裝uv-CSDN博客 https://zhuanlan.zhihu.com/p/6776864377 使用方式 方式1&#xff1a; 創建uv虛擬環境->激活環境->安裝依賴&…

C#實現Socket通信:基于TCP/IP協議的網絡編程

TCP/IP網絡模型 最上層的是應用層&#xff0c;也就是我們日常可以接觸到的&#xff0c;它會給數據添加對應的頭部&#xff0c;并傳輸給傳輸層&#xff0c;應用層是我們日常會接觸到的&#xff0c;比如HTTP&#xff0c;FTP&#xff0c;Telnet&#xff0c;DNS&#xff0c;SMTP。…

哈希算法、搜索算法與二分查找算法在 C# 中的實現與應用

在計算機科學中&#xff0c;哈希算法、搜索算法和二分查找算法是三個非常基礎且常用的概念。它們分別在數據存儲、數據查找、以及高效檢索等場景中起著至關重要的作用。在 C# 中&#xff0c;這些算法的實現和使用也十分簡便。本文將詳細講解這三種算法的原理、應用以及 C# 中的…

AI日報 · 2025年5月05日|雅詩蘭黛與微軟合作成立 AI 創新實驗室,加速美妝產品研發與營銷

1、蘋果與 Anthropic 深化合作&#xff0c;內部測試 AI 驅動的新版 Xcode 據多方報道&#xff0c;蘋果公司正與人工智能初創公司 Anthropic 合作&#xff0c;開發集成 AI 功能的新一代 Xcode 開發平臺。該平臺旨在利用 Anthropic 強大的 Claude Sonnet 模型&#xff0c;為開發…

python celery框架結合django的使用

學習目標&#xff1a; 通過文章了解celery的運行機制以及如何結合django去使用 熟悉celery的運行原理屬性celery在django項目當中的配置如何啟動運行celery框架 學習內容&#xff1a; 熟悉celery的運行原理&#xff0c;簡單來說 Celery 是一個“任務排隊機后臺處理器”。幫你…

滑動窗口leetcode 904

代碼&#xff1a; class Solution { public:int totalFruit(vector<int>& fruits) {int n fruits.size();unordered_map<int,int> window_type_count;int left 0;int ans 0;for(int right 0; right <n;right){while(window_type_count.size() 2 &&…

用可視化學習逆置法

1.逆置法思路 目標&#xff1a;將這個彩色數組向右旋轉3步 &#x1f534;1 → &#x1f7e0;2 → &#x1f7e1;3 → &#x1f7e2;4 → &#x1f535;5 → &#x1f7e3;6 → ?7我們希望得到 &#x1f535;5 → &#x1f7e3;6 → ?7 → &#x1f534;1 → &#x1f7e0;…

Cisco Packet Tracer 選項卡的使用

目錄 設備Config選項卡的使用 Realtime and Simulation模式&#xff08;數據包跟蹤與分析&#xff09; 設備Desktop選項卡的使用 設備Config選項卡的使用 Hostname NVRAM Startup Config----Load 加載 INTERFACE 點擊on Save 如果&#xff0c;不把Running Config保存為Sta…

pyqt寫一個單片機配置界面

已經實現以下功能 1.可以選擇單片機架構 2.選擇完單片機架構后第二個框可以選擇常見單片機型號 3.選擇完常見單片機型號后第三個框可以選擇內部資源如adc等&#xff08;可以選擇多個內部資源&#xff09;4.選擇完內部資源如adc等&#xff08;可以選擇多個內部資源&#xff09;后…

丟失的數字 --- 位運算

目錄 一&#xff1a;題目 二&#xff1a;算法原理 三&#xff1a;代碼實現 一&#xff1a;題目 題目鏈接&#xff1a; 268. 丟失的數字 - 力扣&#xff08;LeetCode&#xff09; 二&#xff1a;算法原理 三&#xff1a;代碼實現 class Solution { public:int missingNumb…

千鋒教育Ansible自動化運維實戰教程從入門到精通

簡介 介紹 Ansible 的基本概念、自動化運維優勢、應用場景及課程目標。 歡迎開啟 Ansible 學習之旅&#xff01; 你好&#xff01;作為一名學習者&#xff0c;你即將通過這個 Ansible 自動化運維實戰 課程&#xff0c;從零開始掌握自動化運維的超能力&#xff01;這個“簡介”…

深入理解 TensorFlow 的模型保存與加載機制(SavedModel vs H5)

深入理解 TensorFlow 的模型保存與加載機制&#xff08;SavedModel vs H5&#xff09; 在使用 TensorFlow 進行模型訓練后&#xff0c;模型的保存與加載是部署、復用和遷移學習的重要環節。TensorFlow 提供了兩種主要的保存格式&#xff1a;SavedModel 和 HDF5 (.h5)。本篇文章…

C++之特殊類設計及類型轉換

目錄 一、設計一個不能被拷貝的類 二、設計一個只能在堆上創建對象的類 三、設計一個只能在棧上創建對象的類 四、設計一個不能被繼承的類 五、設計一個只能創建一個對象的類(單例模式) 六、C語言中的類型轉換 七、C中的三類類型轉換 八、C強制類型轉換 8.1、為什么C需…

制作一款打飛機游戲36:調度編輯器

我們正在創建一個調度編輯器。嗯&#xff0c;這個名字聽起來可能有點奇怪&#xff0c;對吧&#xff1f;但如果你了解射擊游戲中的“調度”&#xff0c;那就是敵人出現的時間表。 你可能已經看到了&#xff0c;我們有一個可以滾動的關卡。現在&#xff0c;我想增加一些交互性&a…

wordperss AI插件:AI圖文+視頻+長尾關鍵詞自動生成,已內置deepseek、kimi全模型,支持簡單一鍵接入更多自定義API

【2.17最新版】Linkreate wordperss AI插件&#xff1a;AI圖文視頻長尾關鍵詞自動生成&#xff0c;已內置deepseek、kimi全模型。 支持自定義接入其它API&#xff0c;包括但不限于騰訊云API和它的deepseek模型 后臺只需要設置對應的API url 、模型 、API key,就可以讓插件調用…

從零開始學Python:開啟編程新世界的大門

在當今數字化時代&#xff0c;Python作為一門簡潔、高效且功能強大的編程語言&#xff0c;受到了越來越多人的喜愛與追捧。無論是數據科學、人工智能、Web開發&#xff0c;還是自動化腳本編寫&#xff0c;Python都展現出了卓越的能力。本文將帶領大家踏上Python學習之旅&#x…

【PostgreSQL數據分析實戰:從數據清洗到可視化全流程】3.2 缺失值檢測與處理(NULL值填充/刪除策略)

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 文章大綱 缺失值檢測與處理全攻略&#xff1a;NULL值填充與刪除策略實戰3.2 缺失值檢測與處理3.2.1 缺失值類型與業務影響3.2.1.1 缺失值的三種形態3.2.1.2 業務影響分級 3.2.2 缺失值…

Java求職面試:Spring Boot與微服務的幽默探討

Java求職者面試&#xff1a;技術與幽默的碰撞 場景概述 在某互聯網大廠的面試現場&#xff0c;面試官嚴肅認真&#xff0c;程序員則是一個搞笑的水貨角色。面試者名叫張偉&#xff0c;年齡28歲&#xff0c;碩士學歷&#xff0c;擁有5年的Java開發經驗。以下是面試的詳細過程。…

使用 NGINX 實現 HTTP Basic 認證ngx_http_auth_basic_module 模塊

一、前言 在 Web 應用中&#xff0c;對部分資源進行訪問控制是十分常見的需求。除了基于 IP 限制、JWT 驗證、子請求校驗等方式外&#xff0c;最經典也最簡單的一種方式便是 HTTP Basic Authentication。NGINX 提供的 ngx_http_auth_basic_module 模塊支持基于用戶名和密碼的基…