Java核心类库篇7——多线程
生活随笔
收集整理的這篇文章主要介紹了
Java核心类库篇7——多线程
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Java核心類庫(kù)篇7——多線程
1、程序、進(jìn)程和線程
- 程序 - 數(shù)據(jù)結(jié)構(gòu) + 算法,主要指存放在硬盤上的可執(zhí)行文件
- 進(jìn)程 - 主要指運(yùn)行在內(nèi)存中的可執(zhí)行文件
- 線程就是進(jìn)程內(nèi)部的程序流
操作系統(tǒng)內(nèi)部支持多 進(jìn)程的,而每個(gè)進(jìn)程的內(nèi)部又是支持多線程的
2、線程的創(chuàng)建
| public Thread() | 使用無(wú)參的方式構(gòu)造對(duì)象 |
| public Thread(String name) | 根據(jù)參數(shù)指定的名稱來(lái)構(gòu)造對(duì)象 |
| public Thread(Runnable target) | 根據(jù)參數(shù)指定的引用來(lái)構(gòu)造對(duì)象,其中Runnable是個(gè)接口類型 |
| public Thread(Runnable target, String name) | 根據(jù)參數(shù)指定引用和名稱來(lái)構(gòu)造對(duì)象 |
| public void run() | 若使用Runnable引用構(gòu)造了線程對(duì)象,調(diào)用該方法時(shí)最終調(diào) 用接口中的版本 若沒(méi)有使用Runnable引用構(gòu)造線程對(duì)象,調(diào)用該方法時(shí)則啥也不做 |
| public void start() | 用于啟動(dòng)線程,Java虛擬機(jī)會(huì)自動(dòng)調(diào)用該線程的run方法 |
| public long getId() | 獲取調(diào)用對(duì)象所表示線程的編號(hào) |
| public String getName() | 獲取調(diào)用對(duì)象所表示線程的名稱 |
| public void setName(String name) | 設(shè)置/修改線程的名稱為參數(shù)指定的數(shù)值 |
| public static Thread currentThread() | 獲取當(dāng)前正在執(zhí)行線程的引用 |
2.1、繼承Thread類
- 優(yōu)點(diǎn):實(shí)現(xiàn)起來(lái)簡(jiǎn)單,而且要獲取當(dāng)前線程,無(wú)需調(diào)用Thread.currentThread()方法,直接使用this即可獲取當(dāng)前線程
- 缺點(diǎn):線程類已經(jīng)繼承Thread類了,就不能再繼承其他類,多個(gè)線程不能共享同一份資源
注:直接調(diào)用run方法如同調(diào)用類成員方法一樣
2.2、實(shí)現(xiàn)Runnable接口
- 優(yōu)點(diǎn):線程類只是實(shí)現(xiàn)了接口,還可以繼承其他類,多個(gè)線程可以使用同一個(gè)target對(duì)象,適合多個(gè)線程處理同一份資源的情況
- 缺點(diǎn):通過(guò)這種方式實(shí)現(xiàn)多線程,相較于第一類方式,編程較復(fù)雜,要訪問(wèn)當(dāng)前線程,必須調(diào)用Thread.currentThread()方法
2.3、Callable和FutureTask
- 優(yōu)點(diǎn):線程類只是實(shí)現(xiàn)了接口,還可以繼承其他類,多個(gè)線程可以使用同一個(gè)target對(duì)象,適合多個(gè)線程處理同一份資源的情況
- 缺點(diǎn):通過(guò)這種方式實(shí)現(xiàn)多線程,相較于第一類方式,編程較復(fù)雜,要訪問(wèn)當(dāng)前線程,必須調(diào)用Thread.currentThread()方法
lambda表達(dá)式
public class Test {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<Integer> futureTask = new FutureTask<>((Callable<Integer>) () -> {System.out.println("hello world!");return 100;});new Thread(futureTask, "ruoye").start();for (int i = 0; i < 50; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}System.out.println(futureTask.get());} }3、線程優(yōu)先級(jí)及線程讓步
| public static void yield() | 當(dāng)前線程讓出處理器(離開(kāi)Running狀態(tài)),使當(dāng)前線程進(jìn)入Runnable 狀態(tài)等待 |
| public static void sleep(times) | 使當(dāng)前線程從 Running 放棄處理器進(jìn)入Block狀態(tài), 休眠times毫秒 |
| public int getPriority() | 獲取線程的優(yōu)先級(jí) |
| public void setPriority(int newPriority) | 修改線程的優(yōu)先級(jí),優(yōu)先級(jí)越高的線程不一定先執(zhí)行,但該線程獲取到時(shí)間片的機(jī)會(huì)會(huì)更多 一些 |
| public void join() | 等待該線程終止 |
| public void join(long millis) | 等待參數(shù)指定的毫秒數(shù) |
| public boolean isDaemon() | 用于判斷是否為守護(hù)線程 |
| public void setDaemon(boolean on) | 用于設(shè)置線程為守護(hù)線程 |
sleep
public class Test {public static void main(String[] args) {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");while (true){System.out.println(simpleDateFormat.format(new Date()));try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}} }setPriority線程優(yōu)先級(jí)
public class Test {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println(Thread.currentThread().getName()+"優(yōu)先級(jí)-----"+Thread.currentThread().getPriority());for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+"-----"+i);}});thread.setName("ruoye");thread.setPriority(Thread.MAX_PRIORITY);thread.start();for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+"-----"+i);}} }線程等待
public class Test {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-----"+i);}});thread.setName("ruoye");thread.start(); // thread.join(); // System.out.println("終于等到你");thread.join(5000);System.out.println("沒(méi)有等到你");} }守護(hù)線程
public class Test {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-----"+i);}});thread.setName("ruoye");thread.setDaemon(true);thread.start();Thread.sleep(5000);System.out.println("沒(méi)有等到你");} }4、線程同步
4.1、多線程出現(xiàn)的問(wèn)題
public class Account implements Runnable {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic void run() {System.out.println("進(jìn)到門口");System.out.println("開(kāi)始取鈔");if (this.money>200){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}this.money-=200;System.out.println("取款成功");}}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';} } public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1000);Thread thread = new Thread(account);Thread thread1 = new Thread(account);thread.start();thread1.start();thread.join();thread1.join();System.out.println(account.getMoney());} }4.2、synchronized同步鎖
4.2.1、synchronized代碼塊
下面所示為鎖class,鎖Account對(duì)象里的成員變量(對(duì)象)也可,但請(qǐng)時(shí)刻記住,多個(gè)Account為對(duì)象里的成員變量(對(duì)象)多個(gè)對(duì)象,那么就擁有了多把鎖,此時(shí)應(yīng)當(dāng)用static修飾
休眠在同步代碼塊內(nèi)不會(huì)讓出cpu
public class Account implements Runnable {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic void run() {System.out.println("進(jìn)到門口");synchronized (Account.class){System.out.println("開(kāi)始取鈔");if (this.money>200){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}this.money-=200;System.out.println("取款成功");}}}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';} } public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1000);Thread thread = new Thread(account);Thread thread1 = new Thread(account);thread.start();thread1.start();thread.join();thread1.join();System.out.println(account.getMoney());} }4.2.2、synchronized方法
當(dāng)synchronized位于成員方法上等價(jià)于synchronized (this)
當(dāng)當(dāng)synchronized位于成員方法上等價(jià)于synchronized (類對(duì)象)
public class Account implements Runnable {private int money;public Account(int money) {this.money = money;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic synchronized void run() {System.out.println("進(jìn)到門口");System.out.println("開(kāi)始取鈔");if (this.money>200){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}this.money-=200;System.out.println("取款成功");}}@Overridepublic String toString() {return "Account{" +"money=" + money +'}';} } public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1000);Thread thread = new Thread(account);Thread thread1 = new Thread(account);thread.start();thread1.start();thread.join();thread1.join();System.out.println(account.getMoney());} }4.3、死鎖問(wèn)題
盡量減少同步的資源,減少同步代碼塊的嵌套結(jié)構(gòu)的使用
線程一執(zhí)行的代碼
public void run(){synchronized(a){ //持有對(duì)象鎖a,等待對(duì)象鎖b synchronized(b){ //編寫鎖定的代碼; }} }線程二執(zhí)行的代碼
public void run(){synchronized(b){ //持有對(duì)象鎖a,等待對(duì)象鎖b synchronized(a){ //編寫鎖定的代碼; }} }4.4、Lock鎖
- Lock是顯式鎖,需要手動(dòng)實(shí)現(xiàn)開(kāi)啟和關(guān)閉操作,而synchronized是隱式鎖,執(zhí)行鎖定代碼后自動(dòng)釋放
- Lock只有同步代碼塊方式的鎖,而synchronized有同步代碼塊方式和同步方法兩種鎖
- 使用Lock鎖方式時(shí),Java虛擬機(jī)將花費(fèi)較少的時(shí)間來(lái)調(diào)度線程,因此性能更好
5、線程通信
5.1、線程通信
不能鎖class
public class Account implements Runnable {private int a;public Account(int a) {this.a = a;}@Overridepublic void run() {while (true){synchronized (this) {if (a<100){System.out.println(Thread.currentThread().getName()+"========"+a);a++;notify();try {wait();} catch (InterruptedException e) {e.printStackTrace();}}else{break;}}}} } public class Test {public static void main(String[] args) throws InterruptedException {Account account = new Account(1);Thread ruoye = new Thread(account, "ruoye");Thread yoya = new Thread(account, "yoya");ruoye.start();yoya.start();} }5.2、生產(chǎn)者消費(fèi)者問(wèn)題
- 線程間的通信共享數(shù)據(jù)一定要有同步代碼塊synchronized
- 一定要有wait和notify,而且二者一定是成對(duì)出現(xiàn)
- 生產(chǎn)者和消費(fèi)者的線程實(shí)現(xiàn)一定是在while(true)里面
總結(jié)
以上是生活随笔為你收集整理的Java核心类库篇7——多线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用python做逻辑回归梯度上升_机器学
- 下一篇: 的计时器设置_【教程】PPT课件中常见的