摘要:可以用代替可以用代替定義的對(duì)象的值是不可變的今天就先到這里,大家可以看看這些內(nèi)容的拓展記得點(diǎn)關(guān)注看更新,謝謝閱讀
前言
java高并發(fā)第二篇講的是java線程的基礎(chǔ)
依舊不多說廢話
進(jìn)程是操作系統(tǒng)運(yùn)行的基礎(chǔ),是一個(gè)程序運(yùn)行的實(shí)體,windows上打開任務(wù)管理器就能看到進(jìn)程
線程是輕量級(jí)的進(jìn)程,是程序執(zhí)行的最小單位,是在進(jìn)程這個(gè)容器下進(jìn)行的
新建一個(gè)線程類有兩種方式: extends Thread implement Runnable
推薦使用Runnable接口(這不廢話嗎)
1.創(chuàng)建線程
Thread t1 = new Thread(){ @Ovveride public void run(){ System.out.println("create"); } t1.start();
重構(gòu)run()方法,用start()啟動(dòng)線程
2.終止線程
Thread.stop();
不推薦stop,強(qiáng)行終止不能保證原子性
這里給大家寫一個(gè)終止線程的推薦方法:
public class interruptTest { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(){ public void run(){ while (true){ System.out.println("go"); if (Thread.currentThread().isInterrupted()){ break; } } } }; t1.start(); Thread.sleep(10001); t1.interrupt(); } }
看懂了嗎?
方法解釋:
interrupt和stop不同的是,stop會(huì)立即中斷線程,而interrupt的中斷線程由線程自己決定
Thread.interrupt() //設(shè)置中斷標(biāo)志 Thread.isInterrupted() //判斷當(dāng)前線程是否有中斷標(biāo)志,如果有,返回true
sleep()也能讓線程暫時(shí)性的中斷,即讓線程休眠
3.線程協(xié)作之等待和通知
多線程之間的協(xié)作可以使用等待(wait())和通知(notify)進(jìn)行
wait和notify不能亂用,它們必須包含在synchronzied(即同步)的方法中
無論是wait還是notify,都需要一個(gè)目標(biāo)對(duì)象的監(jiān)聽器(也叫鎖)
當(dāng)線程1在一個(gè)同步的object對(duì)象中運(yùn)行的時(shí)候,突然執(zhí)行object.wait()方法,此時(shí)線程停止執(zhí)行,并且退出object對(duì)象,釋放對(duì)象的監(jiān)聽器,線程1進(jìn)入等待隊(duì)列
接著線程2進(jìn)入object對(duì)象,首先拿到object對(duì)象的監(jiān)聽器,當(dāng)線程2執(zhí)行object.notify()方法時(shí),對(duì)象object會(huì)隨機(jī)選擇一個(gè)等待隊(duì)列中的線程,并將其喚醒,然后線程2釋放監(jiān)聽器,那個(gè)被喚醒的線程就會(huì)進(jìn)來
用圖更形象:
4.線程協(xié)作之結(jié)束和謙讓
多線程之間的協(xié)作可以使用結(jié)束(join())和謙讓(yield())進(jìn)行
join()方法就是讓一個(gè)線程加入到另一個(gè)線程,至于怎么個(gè)加入法看下面一個(gè)例子:
public class JoinTest { public volatile static int i=0; public static class JoinThread extends Thread{ @Override public void run(){ for (i=0;i<1000;i++){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { JoinThread joinThread = new JoinThread(); joinThread.start(); System.out.println(i); } }
這個(gè)方法打印出來的i大家肯定知道,一定是0,因?yàn)槲覀冊(cè)谶@個(gè)類的主線程里執(zhí)行,雖然joinThread和主線程一起執(zhí)行了,但是主線程并不會(huì)去理會(huì)joinThread,只管執(zhí)行打印代碼:
再來看看加入join()后的結(jié)果:
現(xiàn)在很容易理解了,因?yàn)閖oinThread線程加入到了主線程中,joinThread的join()讓主線程去等待它完成才執(zhí)行打印,所以會(huì)打印出1000
yield()是謙讓,字面意思,就是我已經(jīng)完成一些最重要的事情了,不想再占著CPU資源,需要休息啊一下,但是能否被分配到CPU資源就不一定了
守護(hù)線程守護(hù)線程是在后臺(tái)默默完成系統(tǒng)服務(wù)的線程,如垃圾回收線程,JIT線程
與之相應(yīng)的是用戶線程,也就是用戶完成業(yè)務(wù)要用的線程
當(dāng)一個(gè)java程序中只剩守護(hù)線程的時(shí)候,JVm就會(huì)自然退出
下面用一段代碼證明:
代碼new Thread().setDaemon(true);就是設(shè)置為守護(hù)線程
public class DaemonTest { public static class DaemonT extends Thread{ public void run(){ while (true){ System.out.println("我還在"); try { Thread.sleep(100); } catch (InterruptedException e) { } } } } public static void main(String[] args) throws InterruptedException { DaemonT daemonT = new DaemonT(); daemonT.setDaemon(true); daemonT.start(); Thread.sleep(2000); } }
上面代碼在主線程運(yùn)行兩秒后,自動(dòng)關(guān)閉應(yīng)用,因?yàn)橹挥惺刈o(hù)線程
線程優(yōu)先級(jí)設(shè)置java的線程優(yōu)先級(jí)可以用1-10表示
數(shù)字越高表示優(yōu)先級(jí)越高
Thread thread1 = new Thread(); thread.setPriority(10);
這樣thread1線程的優(yōu)先級(jí)就是最高的
線程安全與synchronized為了保證線程安全,我們之前講過可以使用volatile保證變量可見性
但是volatile并不能真正的保證線程的安全
使用synchronized保證線程安全,synchronized會(huì)在對(duì)象上加鎖
使同一時(shí)間只能有一個(gè)線程進(jìn)入該對(duì)象
synchronized的用法整理:
指定加鎖對(duì)象:對(duì)給定對(duì)象加鎖,進(jìn)入同步代碼前獲得給定對(duì)象的鎖 直接作用于實(shí)例方法:相當(dāng)于對(duì)當(dāng)前實(shí)例加鎖 直接作用于靜態(tài)(static)方法,相當(dāng)于給當(dāng)前類加鎖
所以要注意在同個(gè)線程指定的監(jiān)聽對(duì)象是new Test()還是test實(shí)例
TipsHashMap的多線程編程是不安全的,可能導(dǎo)致機(jī)子死機(jī),兩個(gè)線程交互next會(huì)進(jìn)入死循環(huán)。可以用ConcurrentHashMap代替
ArrayList可以用Vector代替
Integer定義的對(duì)象的值是不可變的
今天就先到這里,大家可以看看這些內(nèi)容的拓展
記得點(diǎn)關(guān)注看更新,謝謝閱讀
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/70635.html
摘要:今天就先到這里,大家可以看看這些內(nèi)容的拓展記得點(diǎn)關(guān)注看更新,謝謝閱讀 前言 這是一個(gè)長(zhǎng)篇博客,希望大家關(guān)注我并且一起學(xué)習(xí)java高并發(fā)廢話不多說,直接開始 并行和并發(fā) 并行:多個(gè)線程同時(shí)處理多個(gè)任務(wù)并發(fā):多個(gè)線程處理同個(gè)任務(wù),不一定要同時(shí) 下面用圖來描述并行和并發(fā)的區(qū)別:(實(shí)現(xiàn)和虛線表示兩個(gè)不同的線程) showImg(https://segmentfault.com/img/bVYT...
摘要:前言今天講的多線程的同步控制直接進(jìn)入正題重入鎖重入鎖可以完全代替,它需要類來實(shí)現(xiàn)下面用一個(gè)簡(jiǎn)單的例子來實(shí)現(xiàn)重入鎖以上代碼打印出來的是,可以說明也實(shí)現(xiàn)了線程同步它相比更加靈活,因?yàn)橹厝腈i實(shí)現(xiàn)了用戶自己加鎖,自己釋放鎖記得一定要釋放,不然其他線 前言 今天講的多線程的同步控制直接進(jìn)入正題 ReentrantLock重入鎖 重入鎖可以完全代替synchronized,它需要java.util...
摘要:前言這篇主要來講解多線程中一個(gè)非常經(jīng)典的設(shè)計(jì)模式包括它的基礎(chǔ)到拓展希望大家能夠有所收獲生產(chǎn)者消費(fèi)者模式簡(jiǎn)述此設(shè)計(jì)模式中主要分兩類線程生產(chǎn)者線程和消費(fèi)者線程生產(chǎn)者提供數(shù)據(jù)和任務(wù)消費(fèi)者處理數(shù)據(jù)和任務(wù)該模式的核心就是數(shù)據(jù)和任務(wù)的交互點(diǎn)共享內(nèi)存緩 前言 這篇主要來講解多線程中一個(gè)非常經(jīng)典的設(shè)計(jì)模式包括它的基礎(chǔ)到拓展希望大家能夠有所收獲 生產(chǎn)者-消費(fèi)者模式簡(jiǎn)述 此設(shè)計(jì)模式中主要分兩類線程:生產(chǎn)者...
摘要:前言本篇主要講解如何去優(yōu)化鎖機(jī)制或者克服多線程因?yàn)殒i可導(dǎo)致性能下降的問題線程變量有這樣一個(gè)場(chǎng)景,前面是一大桶水,個(gè)人去喝水,為了保證線程安全,我們要在杯子上加鎖導(dǎo)致大家輪著排隊(duì)喝水,因?yàn)榧恿随i的杯子是同步的,只能有一個(gè)人拿著這個(gè)唯一的杯子喝 前言 本篇主要講解如何去優(yōu)化鎖機(jī)制或者克服多線程因?yàn)殒i可導(dǎo)致性能下降的問題 ThreadLocal線程變量 有這樣一個(gè)場(chǎng)景,前面是一大桶水,10個(gè)...
摘要:只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙只有動(dòng)手,你才能真正掌握一門技術(shù)持續(xù)更新中項(xiàng)目地址求求求源碼系列跟一起學(xué)如何寫函數(shù)庫(kù)中高級(jí)前端面試手寫代碼無敵秘籍如何用不到行代碼寫一款屬于自己的類庫(kù)原理講解實(shí)現(xiàn)一個(gè)對(duì)象遵循規(guī)范實(shí)戰(zhàn)手摸手,帶你用擼 Do it yourself!!! 只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙 只有動(dòng)手,你才能真正掌握一門技術(shù) 持續(xù)更新中…… 項(xiàng)目地址 https...
閱讀 2946·2021-11-22 11:56
閱讀 3655·2021-11-15 11:39
閱讀 991·2021-09-24 09:48
閱讀 846·2021-08-17 10:14
閱讀 1423·2019-08-30 15:55
閱讀 2821·2019-08-30 15:55
閱讀 1416·2019-08-30 15:44
閱讀 2866·2019-08-30 10:59