一、join方法 1.該方法為成員方法 2.線程合併 package com.bjpowernode.java_learning; public class D107_1_JoinMethod { public static void main(String[] args) throws Int ...
一、join方法
1.該方法為成員方法
2.線程合併
package com.bjpowernode.java_learning; public class D107_1_JoinMethod { public static void main(String[] args) throws InterruptedException{ Thread t = new Thread (new Processer107()); t.setName("t"); t.start(); //合併線程 t.join();//t和主線程合併,可以理解為兩個棧合併成一個棧了,也就是子線程與主線程合併成一個單線程了 //主線程 for(int i=0;i<5;i++) { System.out.println(Thread.currentThread().getName()+"-->"+i); } } } class Processer107 implements Runnable{ public void run() { for(int i=0;i<5;i++) { try { Thread.sleep(1000); }catch(InterruptedException e) { } System.out.println(Thread.currentThread().getName()+"-->"+i); } } }
二、線程的同步(加鎖)
1.非同步編程模型:線程與線程之間,獨立執行,誰也不等誰。
2.同步編程模型:線程與線程之間,先執行一個,再執行另一個,有執行的先後順序。
3.什麼時候要同步?為什麼引入線程同步?
(1)為了數據安全,例如:銀行取款。但是為了保證數據是安全的,必須加入線程同步機制;
(2)使用線程同步的情形:i.必須是多線程環境;ii.多線程環境共用一個數據;iii.共用的數據涉及到修改操作。
以下程式演示取款例子(這個不使用同步的機制,看看會產生什麼影響)
package com.bjpowernode.java_learning; public class D107_2_SynchronizedMethod { public static void main(String[] args) throws InterruptedException{ //創建一個公共賬戶 Accout107_2 a = new Accout107_2("actno-001",8000.0); Processer107_2 c = new Processer107_2(a); //創建線程對同一個賬戶進行取款 Thread t1 = new Thread(c); Thread t2 = new Thread(c); t1.start(); t2.start(); } } class Accout107_2 { private String actno; private double balance; public Accout107_2(String actno,double balance) { this.actno = actno; this.balance = balance; } public String getActno() { return actno; } public void setActno(String actno) { this.actno = actno; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } //對外提供一個取款的方法 public void withdraw(double money) { double after = this.balance - money; try { //這裡我們故意延遲了一下,可以看出餘額不對了 Thread.sleep(1000); }catch(InterruptedException e){ } this.setBalance(after); } } class Processer107_2 implements Runnable{ //賬戶 Accout107_2 act; //Constructer public Processer107_2(Accout107_2 act) { this.act = act; } public void run() { act.withdraw(1000.0); System.out.println("取款成功,餘額為:"+act.getBalance()); } }
修改一下代碼,來解決上面的問題
我們只需要修改withdram方法即可
public void withdraw(double money) { //把需要同步的代碼,放到同步語句塊中,參數一定要填共用對象 synchronized(this) { double after = this.balance - money; try { //這裡我們故意延遲了一下,可以看出餘額不對了 Thread.sleep(1000); }catch(InterruptedException e){ } this.setBalance(after); } }
總結:加入線程同步機制,可以保證我們的數據是安全的,並且是準確,但是這也是犧牲性能為前提的。
三、synchronized的原理
t1線程和t2線程,t1線程執行到synchronized關鍵字,就會找this對象的對象鎖,如果找到this對象鎖,則進入到同步語句塊中執行程式,當同步語句塊中的代碼執行結束漢字過後,t1線程歸還this的對象鎖。
在t1線程執行同步語句塊的過程中,如果t2線程也過來執行以下代碼,也遇到了synchronized關鍵字,所以也去找this的對象鎖,但是該對象鎖被t1線程持有,只能在這等待this對象鎖歸還。
四、源碼:
D107_1_JoinMethod.java
D107_2_SynchronizedMethod.java
https://github.com/ruigege66/Java/blob/master/D107_1_JoinMethod.java
https://github.com/ruigege66/Java/blob/master/D107_2_SynchronizedMethod.java
2.CSDN:https://blog.csdn.net/weixin_44630050
3.博客園:https://www.cnblogs.com/ruigege0000/
4.歡迎關註微信公眾號:傅里葉變換,個人公眾號,僅用於學習交流,後臺回覆”禮包“,獲取大數據學習資料