java多線程之述解

提及線程 就不得不提進程 他們之間的關係很緊密 java

進程:內存中運行的應用程序 每一個進程都有本身的一塊內存空間 而線程是進程中的一個執行單元 一個進程中能夠有多個線程 多線程的好處就是能夠併發操做程序 將cpu資源利用率最大化 就像咱們生活中同樣 當咱們在一個視屏網站下電影的時候 咱們能夠去作一些其餘的時間 不須要一直等着電影下完再去作不會耗費多餘的時間 這就是多線程的好處安全

如何實現多線程呢多線程

1.繼承Thread類 而後重寫run方法併發

2.實現Runnable接口實現重寫·ide

 
特色
繼承thread類
只適用於單繼承 編寫簡單 能夠直接操做
實現runnable接口
能夠實現多繼承

 

 

 

 

線程的狀態測試

1.新建狀態網站

線程在被建立後就進入了新建狀態 例如Thread thread=newThread();this

2.就緒狀態(也稱爲可執行轉態)spa

線程再被建立後 若是調用了 start();說明該線程隨時準備執行
3.運行狀態
這時線程已經拿到了cpu執行權限 須要注意的是 線程可能沒有被執行完 就被搶了 這時他又會回到就緒狀態
4.阻塞狀態
由於線程放棄了cpu的使用權 暫時中止執行操做 直到線程進入到就緒狀態纔有機會轉到運行狀態
阻塞狀況分爲三種:
       1.等待阻塞:經過調用線程的wait方法 等待線程的執行 (例如 你去銀行取錢的時候 忘記帶銀行卡啦 因此你打電話給你老婆讓他送卡過來 在這段時間裏面你就一直在等待他))
       2.其餘阻塞:經過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態 (例如 去銀行取錢的時候感受有點困 睡着了 別人也進不來)
        3.同步阻塞:
線程在獲取 synchronized同步鎖失敗(由於鎖被其餘線程鎖佔用)他會進入到同步阻塞狀態 也稱只爲死鎖() (例如 你去銀行取錢一直在排隊等 可是別人在銀行atm裏面就一直不出來 可是你不死心 仍是一直在等)
5.死亡狀態
線程執行完退出exit或者因異常退出
 
線程調度
 join() 插隊 讓當前線程執行完了以後在執行其餘線程
join( long millis); 讓出時間讓你先執行 時間到了之後再繼續搶
yield(); 暫停此次執行機會 再來競爭(至關於讓你一次)
sleep() 讓此線程休眠多長時間
notify()   喚醒在此對象監視器上等待的單個線程。
notifyAll()  喚醒在此對象監視器上等待的全部線程。
wait()    讓當前線程處於「等待(阻塞)狀態」,「直到其餘線程調用此對象的 notify() 方法或 notifyAll() 方法」,當前線程被喚醒(進入「就緒狀態」)。
 
java線程安全
當多個線程去操做同一對象的同一個屬性時,執行的結果可能與預期不符。這時 這個對象就稱爲線程不安全的對象  這個對象所在的類成爲線程不安全類
這時咱們有兩種方法能夠解決
1.同步方法 
只須要在方法上添加一個synchronized修飾符便可 
       這種方法很是簡單 可是效率很低 由於他把全部的操做都上鎖了(例如去銀行取錢應該是一個完整的操做 咱們只須要將取卡 插卡 取錢 拿卡這幾部上鎖就夠了 由於咱們取錢的時候卡已經拿出來了放在手上 若是等到我了 我直接就能夠去插卡了 很快 可是若是我取卡的步驟放到atm機裏面去 找了很半天才找到卡是否是很浪費時間 若是每一個人都是這樣時間更長 因此說我在外面將卡找好了就能夠節省時間)
2.同步代碼塊
須要將那些一塊兒執行的代瑪寫在代碼塊中
synchronized(這裏是一個鎖對象 這個鎖對象必須是一個不會改變的對象){
                   這裏寫的是那些須要一塊兒執行的代碼塊
}
 
接下來舉例說明
去銀行取錢若是使用單線程會發生什麼?
 1 package com.newroad.thread.test;  2 //帳戶類
 3 public class Account {  4     private double balance;  5     private Object lock=new Object();  6     public Account(double balance) {  7         super();  8         this.balance = balance;  9  } 10     public  void withdrawMoney(double money) { 11     String name=Thread.currentThread().getName(); 12     System.out.println(name+"取款前帳戶餘額爲:"+balance); 13         if (balance>=money) { 14             balance=balance-money; 15             System.out.println(name+"取款金額爲:"+money +"取款後,餘額爲:"+balance); 16         }else { 17             System.out.println(name+"餘額不足,帳戶餘額爲:"+balance+"取款金額爲;"+money); 18  } 19         
20  } 21 
3
34 
35 } 36 
37 //線程類
38 package com.newroad.thread.test;
40 public class PersonThread extends Thread { 41     private Account account; 42     private double drawbalance; 43     public PersonThread(Account account, double drawbalance) { 44         super(); 45         this.account = account; 46         this.drawbalance = drawbalance; 47  } 48 
49  @Override 50     public void run() { 51  account.withdrawMoney(drawbalance); 52 
53  } 54 
55 } 56 
57 
58 //這是測試類
59 package com.newroad.thread.test; 60 
61 public class Test { 62 public static void main(String[] args) { 63     Account account=new Account(4000); 64     PersonThread p=new PersonThread(account, 2400); 65     PersonThread p1=new PersonThread(account, 1000); 66     PersonThread p2=new PersonThread(account, 600); 67     p.setName("張三"); 68     p1.setName("張三媳婦"); 69     p2.setName("張三爸"); 70  p.start(); 71  p1.start(); 72  p2.start(); 73  } 74 }

 

 這是運行後的結果 明顯不對 咱們能夠明顯發現 只有張三的操做是沒有問題的 他媳婦和他爸都是有問題的 這確定是有問題的 這時就可使用加鎖的方法 讓一個線程執行完了在讓其餘線程在執行 而生活中 咱們去銀行ATM機上取錢都會有一個門 等我全部操做都完了其餘人才能進來 這就至關於咱們程序中的鎖
這時咱們只須要修改 帳戶類就能夠啦
 1 package com.newroad.thread.test;  2  3 public class Account {  4 private double balance;  5 private Object lock = new Object();  6  7 public Account(double balance) {  8 super();  9 this.balance = balance; 10  } 11 public void withdrawMoney(double money) { 12 String name = Thread.currentThread().getName(); 13 synchronized (this) { 14 System.out.println(name + "取款前帳戶餘額爲:" + balance); 15 if (this.balance >= money) { 16 balance = balance - money; 17 System.out.println(name + "取款金額爲:" + money + "取款後,餘額爲:" + balance); 18 } else { 19 System.out.println(name + "餘額不足,帳戶餘額爲:" + balance + "取款金額爲;" + money); 20  } 21  } 22  } 23 24 }

這時咱們就能夠發現就沒問題了線程

相關文章
相關標籤/搜索