Java核心类库篇7——多线程
生活随笔
收集整理的這篇文章主要介紹了
Java核心类库篇7——多线程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Java核心類庫篇7——多線程
1、程序、進程和線程
- 程序 - 數據結構 + 算法,主要指存放在硬盤上的可執行文件
- 進程 - 主要指運行在內存中的可執行文件
- 線程就是進程內部的程序流
操作系統內部支持多 進程的,而每個進程的內部又是支持多線程的
2、線程的創建
| public Thread() | 使用無參的方式構造對象 |
| public Thread(String name) | 根據參數指定的名稱來構造對象 |
| public Thread(Runnable target) | 根據參數指定的引用來構造對象,其中Runnable是個接口類型 |
| public Thread(Runnable target, String name) | 根據參數指定引用和名稱來構造對象 |
| public void run() | 若使用Runnable引用構造了線程對象,調用該方法時最終調 用接口中的版本 若沒有使用Runnable引用構造線程對象,調用該方法時則啥也不做 |
| public void start() | 用于啟動線程,Java虛擬機會自動調用該線程的run方法 |
| public long getId() | 獲取調用對象所表示線程的編號 |
| public String getName() | 獲取調用對象所表示線程的名稱 |
| public void setName(String name) | 設置/修改線程的名稱為參數指定的數值 |
| public static Thread currentThread() | 獲取當前正在執行線程的引用 |
2.1、繼承Thread類
- 優點:實現起來簡單,而且要獲取當前線程,無需調用Thread.currentThread()方法,直接使用this即可獲取當前線程
- 缺點:線程類已經繼承Thread類了,就不能再繼承其他類,多個線程不能共享同一份資源
注:直接調用run方法如同調用類成員方法一樣
2.2、實現Runnable接口
- 優點:線程類只是實現了接口,還可以繼承其他類,多個線程可以使用同一個target對象,適合多個線程處理同一份資源的情況
- 缺點:通過這種方式實現多線程,相較于第一類方式,編程較復雜,要訪問當前線程,必須調用Thread.currentThread()方法
2.3、Callable和FutureTask
- 優點:線程類只是實現了接口,還可以繼承其他類,多個線程可以使用同一個target對象,適合多個線程處理同一份資源的情況
- 缺點:通過這種方式實現多線程,相較于第一類方式,編程較復雜,要訪問當前線程,必須調用Thread.currentThread()方法
lambda表達式
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、線程優先級及線程讓步
| public static void yield() | 當前線程讓出處理器(離開Running狀態),使當前線程進入Runnable 狀態等待 |
| public static void sleep(times) | 使當前線程從 Running 放棄處理器進入Block狀態, 休眠times毫秒 |
| public int getPriority() | 獲取線程的優先級 |
| public void setPriority(int newPriority) | 修改線程的優先級,優先級越高的線程不一定先執行,但該線程獲取到時間片的機會會更多 一些 |
| public void join() | 等待該線程終止 |
| public void join(long millis) | 等待參數指定的毫秒數 |
| public boolean isDaemon() | 用于判斷是否為守護線程 |
| public void setDaemon(boolean on) | 用于設置線程為守護線程 |
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線程優先級
public class Test {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println(Thread.currentThread().getName()+"優先級-----"+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("沒有等到你");} }守護線程
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("沒有等到你");} }4、線程同步
4.1、多線程出現的問題
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("進到門口");System.out.println("開始取鈔");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對象里的成員變量(對象)也可,但請時刻記住,多個Account為對象里的成員變量(對象)多個對象,那么就擁有了多把鎖,此時應當用static修飾
休眠在同步代碼塊內不會讓出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("進到門口");synchronized (Account.class){System.out.println("開始取鈔");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方法
當synchronized位于成員方法上等價于synchronized (this)
當當synchronized位于成員方法上等價于synchronized (類對象)
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("進到門口");System.out.println("開始取鈔");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、死鎖問題
盡量減少同步的資源,減少同步代碼塊的嵌套結構的使用
線程一執行的代碼
public void run(){synchronized(a){ //持有對象鎖a,等待對象鎖b synchronized(b){ //編寫鎖定的代碼; }} }線程二執行的代碼
public void run(){synchronized(b){ //持有對象鎖a,等待對象鎖b synchronized(a){ //編寫鎖定的代碼; }} }4.4、Lock鎖
- Lock是顯式鎖,需要手動實現開啟和關閉操作,而synchronized是隱式鎖,執行鎖定代碼后自動釋放
- Lock只有同步代碼塊方式的鎖,而synchronized有同步代碼塊方式和同步方法兩種鎖
- 使用Lock鎖方式時,Java虛擬機將花費較少的時間來調度線程,因此性能更好
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、生產者消費者問題
- 線程間的通信共享數據一定要有同步代碼塊synchronized
- 一定要有wait和notify,而且二者一定是成對出現
- 生產者和消費者的線程實現一定是在while(true)里面
總結
以上是生活随笔為你收集整理的Java核心类库篇7——多线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用python做逻辑回归梯度上升_机器学
- 下一篇: java控制层创建websocket_用