<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
由於本週大部分時間都在寫原型,主要遇到的問題就是對實際功能理解不準確導致多次修改原型浪費了很多時間,這也就告訴我們一定要明確實際要求再去下手。
因為之前會議中也多次提到了執行緒,而我本人對執行緒沒有什麼理解於是便有了以下文章。
在我們開發系統過程中,經常會處理一些費時間的任務(如:向資料庫中插入大量資料),這個時候就就需要使用多執行緒。
是,Spring中可直接由@Async實現多執行緒操作
通過設定執行緒池。
執行緒池ThreadPoolExecutor執行規則如下
然後我們來認為構造一個執行緒池來試一下:
@Configuration @EnableAsync public class ThreadPoolConfig implements AsyncConfigurer { /** * 核心執行緒池大小 */ private static final int CORE_POOL_SIZE = 3; /** * 最大可建立的執行緒數 */ private static final int MAX_POOL_SIZE = 10; /** * 佇列最大長度 */ private static final int QUEUE_CAPACITY = 10; /** * 執行緒池維護執行緒所允許的空閒時間 */ private static final int KEEP_ALIVE_SECONDS = 300; /** * 非同步執行方法執行緒池 * * @return */ @Override @Bean public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setMaxPoolSize(MAX_POOL_SIZE); executor.setCorePoolSize(CORE_POOL_SIZE); executor.setQueueCapacity(QUEUE_CAPACITY); executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS); executor.setThreadNamePrefix("LiMingTest"); // 執行緒池對拒絕任務(無執行緒可用)的處理策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }
ThreadPoolExecutor是JDK中的執行緒池實現,這個類實現了一個執行緒池需要的各個方法,它提供了任務提交、執行緒管理、監控等方法。
執行緒池維護的最小執行緒數量,預設情況下核心執行緒建立後不會被回收(注意:設定allowCoreThreadTimeout=true後,空閒的核心執行緒超過存活時間也會被回收)。
大於核心執行緒數的執行緒,在空閒時間超過keepAliveTime後會被回收。
執行緒池允許建立的最大執行緒數量。
當新增一個任務時,核心執行緒數已滿,執行緒池還沒達到最大執行緒數,並且沒有空閒執行緒,工作佇列已滿的情況下,建立一個新執行緒,然後從工作佇列的頭部取出一個任務交由新執行緒來處理,而將剛提交的任務放入工作佇列尾部。
當一個可被回收的執行緒的空閒時間大於keepAliveTime,就會被回收。
被回收的執行緒:
設定allowCoreThreadTimeout=true的核心執行緒。
大於核心執行緒數的執行緒(非核心執行緒)。
新任務被提交後,如果核心執行緒數已滿則會先新增到工作佇列,任務排程時再從佇列中取出任務。工作佇列實現了BlockingQueue介面。
當執行緒池執行緒數已滿,並且工作佇列達到限制,新提交的任務使用拒絕策略處理。可以自定義拒絕策略,拒絕策略需要實現RejectedExecutionHandler介面。
JDK預設的拒絕策略有四種:
AbortPolicy:丟棄任務並丟擲RejectedExecutionException異常。
DiscardPolicy:丟棄任務,但是不丟擲異常。可能導致無法發現系統的異常狀態。
DiscardOldestPolicy:丟棄佇列最前面的任務,然後重新提交被拒絕的任務。
CallerRunsPolicy:由呼叫執行緒處理該任務。
我們在非測試檔案中直接使用new Thread建立新執行緒時編譯器會發出警告:
不要顯式建立執行緒,請使用執行緒池。
說明:使用執行緒池的好處是減少在建立和銷燬執行緒上所花的時間以及系統資源的開銷,解決資源不足的問題。如果不使用執行緒池,有可能造成系統建立大量同類執行緒而導致消耗完記憶體或者“過度切換”的問題
public class TestServiceImpl implements TestService { private final static Logger logger = LoggerFactory.getLogger(TestServiceImpl.class); @Override public void task(int i) { logger.info("任務: "+i); } }
@Autowired TestService testService; @Test public void test() { for (int i = 0; i < 50; i++) { testService.task(i); }
我們可以看到一切執行正常;
之後我有對執行緒進行了一些測試:
class TestServiceImplTest { @Test public void test() { Thread add = new AddThread(); Thread dec = new DecThread(); add.start(); dec.start(); add.join(); dec.join(); System.out.println(Counter.count); } static class Counter { public static int count = 0; } class AddThread extends Thread { public void run() { for (int i=0; i<10000; i++) { Counter.count += 1; } } } class DecThread extends Thread { public void run() { for (int i=0; i<10000; i++) { Counter.count -= 1; } } }
一個自增執行緒,一個自減執行緒,對0進行同樣次數的操作,理應結果仍然為零,但是執行結果卻每次都不同。
經過搜尋之後發現對變數進行讀取和寫入時,結果要正確,必須保證是原子操作。原子操作是指不能被中斷的一個或一系列操作。
例如,對於語句: n +=1; 看似只有一行語句卻包括了3條指令:
讀取n, n+1, 儲存n;
比如有以下兩個程序同時對10進行加1操作
這說明多執行緒模型下,要保證邏輯正確,對共用變數進行讀寫時,必須保證一組指令以原子方式執行:即某一個執行緒執行時,其他執行緒必須等待。
static class Counter { public static final Object lock = new Object();//每個執行緒都需獲得鎖才能執行 public static int count = 0; } class AddThread extends Thread { public void run() { for (int i=0; i<10000; i++) { synchronized(Counter.lock) { static class Counter { public static final Object lock = new Object(); public static int count = 0; } class DecThread extends Thread { public void run() { for (int i=0; i<10000; i++) { synchronized(Counter.lock) { Counter.count -= 1; } } } }
值得注意的是每個類可以設定多個鎖,如果執行緒獲取的不是同一個鎖則無法起到上述功能;
springBoot中也定義了很多型別的鎖,在此就不一一說明了,我們目前能做到的就是注意專案中的非同步操作,觀察操作所使用的執行緒,做到在以後專案中遇到此類問題時能及時發現問題,解決問題。
到此這篇關於Spring多執行緒的使用及問題的文章就介紹到這了,更多相關Spring多執行緒使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45