package thread;
//繼承Thread類
public class Day1 extends Thread{
// 重寫run()方法
@Override
public void run() {
System.out.println("執行緒運行的代碼");
for (int i = 0; i < 5; i++) {
System.out.println("這是邏輯代碼"+i);
}
}
}
/**
* @author
* 開啟run()方法后,run()方法的執行與mian()方法的執行互不相干,類似河流是倆條支流
* 控制臺的結果是兩個方法的總和
* 這個就是多執行緒的異步,是相對于start方法來說的,是并行執行沒有先后順序
*/
public class Test {
public static void main(String[] args) {
Thread day1 = new Day1();
// 啟動
System.out.println("++++");
day1.start();
System.out.println("++++");
System.out.println("++++");
}
}
//實作 Runnable介面
public class Test implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"執行緒運行的代碼");
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"這是邏輯代碼"+i);
}
}
}
public class Test1 {
public static void main(String[] args) {
// 通過Thread創建實體
Thread thread = new Thread(new Test());
thread.start();
// 追加引數創建物件,這個可以獲得執行緒名稱,可以用來區分列印的資料是哪一個執行緒執行
Thread thread1 = new Thread(new Test(),"tt");
thread1.start();
}
}
并發與并行
并發:指兩個或多個事件在同一時間內發生
并行:指兩個或多個事件在同一時刻(同時發生)
行程
一個在記憶體中運行的應用程式,每個行程都有自己獨立的一塊記憶體空間,一個行程可以有多個執行緒,比如在Windows系統中,一個運行的xx.exe就是一個行程,
行程是資源分配的最小單位,執行緒是程式執行的最小單位(資源調度的最小單位)
行程有自己的獨立地址空間,每啟動一個行程,系統就會為它分配地址空間,建立資料表來維護代碼段、堆疊段和資料段,這種操作非常昂貴,
執行緒
行程中的一個執行任務(控制單元),負責當前行程中程式的執行,一個行程至少有一個執行緒,一個行程可以運行多個執行緒,多個執行緒可共享資料,
而執行緒是共享行程中的資料的,使用相同的地址空間,因此CPU切換一個執行緒的花費遠比行程要小很多,同時創建一個執行緒的開銷也比行程要小很多,
繼承與實作的區別
繼承:執行緒代碼存放在Thread子類run方法中
實作:執行緒代碼存放在介面的子類run方法
實作方法的好處
避免單繼承的局限性
多個執行緒可以共享同一個介面實作類的物件,非常適合多個執行緒來處理同一份資源
使用多執行緒的有點
提高應用程式的回應
提高計算機系統cpu的利用率
改善程式結構
執行緒的生命周期
執行緒的同步
package thread;
/**
* 多執行緒呼叫這個方法,執行緒的資源共享,一個執行緒執行這個方法沒有結束,另一個執行緒也開始執行了
*
* 多執行緒安全問題:多條陳述句同時操作一個執行緒共享資料時,會導致共享資料的錯誤
* 解決方法:讓一個執行緒執行結束,再接下一個
*
* 通過synchronized同步鎖來完成
* 可以直接在方法上加上這個關鍵字,這個鎖是鎖整個物件,不是某一個方法
* 普通方法加這個關鍵字就是不同物件就是不同鎖,執行緒使用不同的此方法的物件,還是會出現資源共享問題
* 靜態方法加這個關鍵字:對于所有物件都是同一個鎖
*/
public class Test0 {
public static void main(String[] args) {
// 定義賬戶物件
Acount a = new Acount();
// 定義多執行緒物件
Ures ures = new Ures(a,3000);
Ures ures1 = new Ures(a,3000);
Thread t = new Thread(ures,"微信");
Thread t1 = new Thread(ures1,"支付寶");
t.start();
t1.start();
}
}
class Acount{
public static int money = 3000;
// 同步鎖
// 靜態同步鎖 public statiac synchronized void drawing(int m) {
// public synchronized void drawing(int m) {
public void drawing(int m) {
synchronized (this){//表示當前物件的代碼塊被加了同步鎖 synchronized (this)的代碼塊使用的都是同一個同步鎖
// 用this鎖代碼塊是代表當前的物件,如果在其他方法中也有
if (money < m) {
System.out.println("金額不足" + money);
} else {
System.out.println(Thread.currentThread().getName() + "賬戶原來金額"+money);
System.out.println(Thread.currentThread().getName() + "取款金額" + m);
money -= m;
System.out.println(Thread.currentThread().getName() + "取款后" + money);
}}
}
}
class Ures implements Runnable{
Acount acount;
int money;
public Ures( Acount acount,int money){
this.acount=acount;
this.money=money;
}
@Override
public void run() {
acount.drawing(money);
}
}

如果針對物件要加同步鎖,那就加在方法上
如果針對某一段代碼需要加同步鎖,那就直接加在代碼上
執行緒的死鎖問題
1、不同的執行緒分別占用對方需要的同步資源不放棄,都在等待對方放棄自己需要的同步資源,就形成了執行緒的死鎖,
2、出現死鎖后,不會出現例外,不會出現提示,知識所有執行緒都處于阻塞狀態,無法繼續,
解決方法
1、專門的演算法、原則
2、盡量減少同步資源的定義
3、盡量避免嵌套同步
執行緒通信
這三個方法只能用在有同步鎖的代碼塊或方法上
package thread;
/**
*
*/
public class Test0 {
public static void main(String[] args) {
// 定義賬戶物件
Acount a = new Acount();
// 定義多執行緒物件
Ures ures = new Ures(a,3000);
Ures ures1 = new Ures(a,3000);
Thread t = new Thread(ures,"微信");
Thread t1 = new Thread(ures1,"支付寶");
t.start();
t1.start();
}
}
class Acount{
public static int money = 3000;
public void drawing(int m,Acount a) {
synchronized (a){
// 如果是微信操作的,先不執行,等支付寶操作,支付寶操作完,微信再執行
if ("微信".equals(Thread.currentThread().getName())) {
try {
a.wait();//當前執行緒進入等待阻塞狀態
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (money < m) {
System.out.println(Thread.currentThread().getName()+"金額不足" + money);
} else {
System.out.println(Thread.currentThread().getName() + "賬戶原來金額"+money);
System.out.println(Thread.currentThread().getName() + "取款金額" + m);
money -= m;
System.out.println(Thread.currentThread().getName() + "取款后" + money);
}
if ("支付寶".equals(Thread.currentThread().getName())){
a.notify();//喚醒當前執行緒優先級最高的,進入就緒狀態
// a.notifyAll();//喚醒當前所有執行緒,進入就緒狀態
}
}
}
}
class Ures implements Runnable{
Acount acount;
int money;
public Ures( Acount acount,int money){
this.acount=acount;
this.money=money;
}
@Override
public void run() {
acount.drawing(money,acount);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/259855.html
標籤:其他
下一篇:Java記憶體模型
