首頁 类库下载 java类库 Java多執行緒基本使用

Java多執行緒基本使用

Nov 14, 2016 am 09:32 AM

一、概念

1.進程

1.1進程:是一個正在進行中的程序,每一個進程執行都有一個執行順序,該順序是一個執行路徑,或者叫一個控制單元。

1.2執行緒:就是進程中一個獨立的控制單元,執行緒在控制進程的執行,一個行程中至少有一個執行緒。

1.3舉例java VM:

Java VM啟動的時候會有一個進程java.exe,該進程中至少有一個執行緒在負責java程式的運行,而且這個執行緒運行的程式碼存在於main方法中,該執行緒稱為主線程。擴充:其實更細節說明jvm,jvm啟動不只一個線程,還有負責垃圾回收機制的線程

2.多線程存在的意義:提高執行效率

二、多線程的創建

1.多線程創建的第一種方式,繼承Thread類別

1.1定義類別繼承Thread,複寫Thread類別中的run方法是為了將自訂的程式碼儲存到run方法中,讓執行緒執行

1.2呼叫執行緒的start方法,該呼叫執行緒的start方法,該執行緒執行

1.2呼叫執行緒的start方法,該呼叫執行緒的start方法,該執行緒執行

1.2呼叫執行緒的start方法,該呼叫執行緒該方法方法有兩個作用:啟動線程,呼叫run方法

1.3多線程運行的時候,運行結果每次都不同,因為多個線程都獲取cpu的執行權,cpu執行到誰,誰就運行,明確一點,在某一個時刻,只能有一個程式在運作。 (多核心除外),cpu在做著快速的切換,以到達看上去是同時運行的效果。我們可以形象把多執行緒的運行行為在互搶cpu的執行權。這就是多執行緒的一個特性,隨機性。誰搶到,誰執行,至於執行多久,cpu說了算。

public class Demo extends Thread{ 
    public void run(){ 
        for (int x = 0; x < 60; x++) { 
            System.out.println(this.getName()+"demo run---"+x); 
        } 
    } 
     
    public static void main(String[] args) { 
        Demo d=new Demo();//创建一个线程 
        d.start();//开启线程,并执行该线程的run方法 
        d.run(); //仅仅是对象调用方法,而线程创建了但并没有运行 
        for (int x = 0; x < 60; x++) { 
            System.out.println("Hello World---"+x); 
        } 
    } 
 
}
登入後複製

2 建立多執行緒的第二種方式,步驟:

2.1定義類別實作Runnable介面

2.2覆寫Runnable介面中的run方法:將執行緒要執行的程式碼存放到run方法中

2.3. Thread類別建立執行緒物件

2.4.將Runnable介面的子類別物件作為實際參數傳遞給Thread類別的建構子

為什麼要將Runnable介面的子類別物件傳遞給Thread的建構子:因為自訂的run方法所屬的對像是Runnable介面的子類對象,所以要讓執行緒去執行指定對象的run方法,就必須明確該run方法的所屬對象

2.5.呼叫Thread類別的start方法開啟執行緒並呼叫Runnable介面子類的方法

/* 
 * 需求:简易买票程序,多个窗口同时卖票 
 */ 
public class Ticket implements Runnable { 
    private static int tick = 100; 
    Object obj = new Object(); 
    boolean flag=true; 
 
    public void run() { 
        if(flag){ 
            while (true) { 
                synchronized (Ticket.class) { 
                    if (tick > 0) { 
                        System.out.println(Thread.currentThread().getName() 
                                + "code:" + tick--); 
                    } 
                } 
            } 
        }else{ 
            while(true){ 
                show(); 
            } 
        } 
         
    } 
 
    public static synchronized void show() { 
        if (tick > 0) { 
            System.out.println(Thread.currentThread().getName() + "show:" 
                    + tick--); 
        } 
    } 
 
} 
 
class ThisLockDemo { 
    public static void main(String[] args) { 
        Ticket t = new Ticket(); 
 
        Thread t1 = new Thread(t); 
        try { 
            Thread.sleep(10); 
        } catch (Exception e) { 
            // TODO: handle exception 
        } 
        t.flag=false; 
        Thread t2 = new Thread(t); 
        //Thread t3 = new Thread(t); 
        //Thread t4 = new Thread(t); 
 
        t1.start(); 
        t2.start(); 
        //t3.start(); 
        //t4.start(); 
    } 
}
登入後複製

3.實作方式和繼承方式有什麼區別

3.1.實作方式避免了單繼承的局限性,在定義執行緒時建議使用實作方式

3.2.繼承Thread類別:執行緒程式碼存放在Thread子類別run方法中

3.3.實作Runnable:執行緒程式碼存放在介面的子類別run方法中

4.多執行緒-run和start的特性

4.1為什麼要覆蓋run方法:

Thread類別用

4.1為什麼要覆蓋run方法呢:

Thread類別用於描述線程,該類別定義了一個功能,用於存儲線程要運行的程式碼,該存儲功能就是run方法,也就是說該Thread類別中的run方法,用於存儲線程要運行的程式碼

5.多執行緒運行狀態

創建執行緒-運行---sleep()/wait()--凍結---notify()---喚醒

創建執行緒-運行---stop()—消亡

創建執行緒-運行---沒搶到cpu執行權—暫時凍結

6.取得執行緒物件及其名稱

6.1.執行緒都有自己預設的名稱,編號從0開始

6.2.static Thread currentThread() :取得目前執行緒物件

6.3.getName():取得執行緒名稱

6.4.設定執行緒名稱:setName()或使用建構子

public class Test extends Thread{ 
     
    Test(String name){ 
        super(name); 
    } 
     
    public void run(){ 
        for (int x = 0; x < 60; x++) { 
            System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x); 
        } 
    } 
} 
 
class ThreadTest{ 
    public static void main(String[] args) { 
        Test t1=new Test("one---"); 
        Test t2=new Test("two+++"); 
        t1.start(); 
        t2.start(); 
        t1.run(); 
        t2.run(); 
        for (int x = 0; x < 60; x++) { 
            System.out.println("main----"+x); 
        } 
    } 
}
登入後複製

三、多執行緒的安全性問題

1.多執行緒出現安全性問題的原因:

1.1.當多條語句在操作同一個執行緒共享資料時,一個執行緒對多條語句只執行了一部分,還沒執行完,另一個執行緒參與進來執行,導致共享資料的錯誤

1.2.解決方法:對多條操作共享資料的語句,只能讓一個執行緒都執行完,在執行過程中,其他執行緒不可以參與執行

1.3.java對於多執行緒的安全性問題提供了專業的解決方式,就是同步程式碼區塊:

Synchronized(物件){需要被同步的程式碼},物件如同鎖,持有鎖的執行緒可以在同步中執行,沒有持有鎖的執行緒即使取得cpu執行權,也進不去,因為沒有取得鎖

2.同步的前提:

2.1.必須要有2個或2個以上執行緒

2.2.必須是多個執行緒使用同一個鎖定

2.3.好處是解決了多執行緒的安全性問題

2.4.弊端是多個執行緒需要判斷鎖,較消耗資源

2.5.同步函數

定義同步函數,在方法錢用synchronized修飾即可

/* 
 * 需求: 
 * 银行有一个金库,有两个储户分别存300元,每次存100元,存3次 
 * 目的:该程序是否有安全问题,如果有,如何解决 
 * 如何找问题: 
 * 1.明确哪些代码是多线程代码 
 * 2.明确共享数据 
 * 3.明确多线程代码中哪些语句是操作共享数据的 
 */ 
 
public class Bank { 
 
    private int sum; 
 
    Object obj = new Object(); 
 
    //定义同步函数,在方法钱用synchronized修饰即可 
    public synchronized void add(int n) { 
        //synchronized (obj) { 
            sumsum = sum + n; 
            try { 
                Thread.sleep(10); 
            } catch (InterruptedException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } 
            System.out.println("sum=" + sum); 
        //} 
 
    } 
 
} 
 
class Cus implements Runnable { 
    private Bank b = new Bank(); 
 
    public void run() { 
        for (int x = 0; x < 3; x++) { 
            b.add(100); 
        } 
    } 
} 
 
class BankDemo { 
    public static void main(String[] args) { 
        Cus c = new Cus(); 
        Thread t1 = new Thread(c); 
        Thread t2 = new Thread(c); 
 
        t1.start(); 
        t2.start(); 
    } 
}
登入後複製

6.同步的鎖

6.1函數需要被物件調用,那麼函數都有一個所屬物件引用,就是this.,所以同步函數使用的鎖是this

6.2.靜態函數的鎖是class物件🎜🎜靜態進記憶體時,記憶體中沒有本類對象,但是一定有該類對應的字節碼文件對象,類名.class,該對象的類型是Class🎜🎜6.3.靜態的同步方法,使用的鎖是該方法所在類的字節碼文件對象,類別名稱.class🎜
/* 
 * 需求:简��买票程序,多个窗口同时卖票 
 */ 
public class Ticket implements Runnable { 
    private static int tick = 100; 
    Object obj = new Object(); 
    boolean flag=true; 
 
    public void run() { 
        if(flag){ 
            while (true) { 
                synchronized (Ticket.class) { 
                    if (tick > 0) { 
                        System.out.println(Thread.currentThread().getName() 
                                + "code:" + tick--); 
                    } 
                } 
            } 
        }else{ 
            while(true){ 
                show(); 
            } 
        } 
         
    } 
 
    public static synchronized void show() { 
        if (tick > 0) { 
            System.out.println(Thread.currentThread().getName() + "show:" 
                    + tick--); 
        } 
    } 
 
} 
 
class ThisLockDemo { 
    public static void main(String[] args) { 
        Ticket t = new Ticket(); 
 
        Thread t1 = new Thread(t); 
        try { 
            Thread.sleep(10); 
        } catch (Exception e) { 
            // TODO: handle exception 
        } 
        t.flag=false; 
        Thread t2 = new Thread(t); 
        //Thread t3 = new Thread(t); 
        //Thread t4 = new Thread(t); 
 
        t1.start(); 
        t2.start(); 
        //t3.start(); 
        //t4.start(); 
    } 
}
登入後複製
🎜7.多線程,單例模式-懶漢式🎜

懒汉式与饿汉式的区别:懒汉式能延迟实例的加载,如果多线程访问时,懒汉式会出现安全问题,可以使用同步来解决,用同步函数和同步代码都可以,但是比较低效,用双重判断的形式能解决低效的问题,加同步的时候使用的锁是该类锁属的字节码文件对象

/* 
 * 单例模式 
 */ 
//饿汉式 
public class Single { 
    private static final Single s=new Single(); 
    private Single(){} 
    public static Single getInstance(){ 
        return s; 
    } 
 
} 
 
//懒汉式 
class Single2{ 
    private static Single2 s2=null; 
    private Single2(){} 
    public static Single2 getInstance(){ 
        if(s2==null){ 
            synchronized(Single2.class){ 
                if(s2==null){ 
                    s2=new Single2();     
                } 
            } 
        } 
        return s2; 
    } 
} 
 
class SingleDemo{ 
    public static void main(String[] args) { 
        System.out.println("Hello World"); 
    } 
}
登入後複製

8.多线程-死锁

同步中嵌套同步会出现死锁

/* 
 * 需求:简易买票程序,多个窗口同时卖票 
 */ 
public class DeadTest implements Runnable { 
    private boolean flag; 
 
    DeadTest(boolean flag) { 
        this.flag = flag; 
    } 
 
    public void run() { 
        if (flag) { 
            synchronized(MyLock.locka){ 
                System.out.println("if locka"); 
                synchronized(MyLock.lockb){ 
                    System.out.println("if lockb"); 
                } 
            } 
        } else { 
            synchronized(MyLock.lockb){ 
                System.out.println("else lockb"); 
                synchronized(MyLock.locka){ 
                    System.out.println("else locka"); 
                } 
            } 
        } 
    } 
} 
 
class MyLock{ 
    static Object locka=new Object(); 
    static Object lockb=new Object(); 
} 
 
class DeadLockDemo { 
    public static void main(String[] args) { 
        Thread t1 = new Thread(new DeadTest(true)); 
        Thread t2 = new Thread(new DeadTest(false)); 
 
        t1.start(); 
        t2.start(); 
    } 
}
登入後複製


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)