1. 程式人生 > >java值多執行緒的總結

java值多執行緒的總結

java多執行緒的放肆有四種
1.繼承Thread類,重寫run方法。
2.實現Runnable介面,重寫run方法,實現Runnable介面的實現類例項物件作為Thread構造器函式的target.
3.通過Callable和FutureTask建立執行緒。
4.建立執行緒池建立執行緒
前面兩種可以歸一類:無返回值,原因很簡單,通過重寫run方法,run方式的返回值是void,
後面兩種可以歸一類:有返回值,通過Callable介面,就要實現call方法,這個方法的返回值就是Object,所以返回的結果可以放在Object物件中所以返回的結果可以放在Object物件中。
Thread class Thread1 extends Thread{
        public Thread1(){

        }
        public void run(){
        System.out.println(Thread.currentThread().getName());
        }
        public static void main(String[] args){
            Thread1 thread1=new Thread1();
            thread1.setName("我是自定義的執行緒1");
            thread1.start();
            System.out.println(Thread.currentThread().toString());
        }
}
//這裡輸出的話
Thread[main,5,main]
我是自定義的執行緒

執行緒實現方式2:通過實現Runnable介面,實現run方法,
介面的實現類的例項作為Thread的target作為引數傳入帶引數的Thread建構函式,通過呼叫start()方法啟動執行緒。
public class Thread2{
    public static void main(String] args){
            System.out.prinyln(Thread.currentTghread().getName());//這是打印出來的資訊。
            Thread t1=new Thread(new MyThread());
            t1.start();
    }
}
class MyThread implements Runnable{
    @Override
    public void run(){
    System.out.println(Thread.currentThread().getName()+"我是通過實現介面的執行緒方式。");
    }
}
執行緒實現方式3:通過Callable和Future建立執行緒
a:建立Callable介面的實現類,並實現call方法。
b:建立Callable實現類的實現,使用FutureTask建立執行緒。
c:使用FutureTask物件作為Thread物件的target建立並啟動執行緒。
d:呼叫FutureTask物件的get()來獲取子執行緒執行結束返回值。
public class Thread3{
        public static void main(String[] args){
            Callable<Obejct> oneCallable=new Tickets<Obejct>();
            FutureTask<> oneTask=new Future<Object>(oneCallable);
            Thread t=new Thread(oneTask);
            System.out.println(Thread.currentThread().getName());
            t.start();
        }
}

下面的例子演示了100個執行緒同時向一個銀行賬戶中存入1元錢,在沒有使用同步機制和使用同步機制情況下的執行情況。

1.在銀行賬戶的存款(deposit)方法上同步(synchronized)關鍵字。
public  class Accout{
    private double balance;

    public synchronized void deposit(double money){/這裡對方法的上鎖後,表示同步方法,
    其他方法就不能訪問同步方法。
            double newBalance =balance+money;
            try{
                    Thread.sleep(10);
            }catch(Exception e){
                e.printStackTrace();
            }
            balance=newBalance;
    }
        public double getBalance(){
        return balance;
        }
}
2.線上程呼叫存款方法時對銀行賬戶進行同步
public class AddMoneyThread implements Runable{
    private Account account;//存入賬戶
    private double money;//存入金額
    public AddMoneyThread(Account account,double money){
    this.account=account;
    this.money=money;
    }
    @Override
    public void run(){
        synchronized(account){//這裡就是相當於同步程式碼塊。
            account.deposit(meney);
        }
    }

}
synchronized關鍵字可以將物件或者方法標記為同步,以實現對物件和方法的互斥訪問,
可以用synchronized(物件){。。。}定義同步程式碼塊。或者在宣告方法時將synchronized作為方法的修飾符。
同步就是阻塞式操作,而一部就是非阻塞式操作。

這裡我們說明的一下就是:實現執行緒繼承Thread和實現Runnable的區別:

我們知道的是一類只能是單繼承,但是可以是多實現。所以繼承Thread類有侷限性,

但是實現Runnable很顯然,我們可以繼承其他類。

接下來我們總結一下悲觀鎖和樂觀鎖的看法。

悲觀鎖:
總是假設最壞的情況,每次取資料都會認為其他執行緒會修改,所以都會加鎖。
當其他執行緒想要訪問資料時,都需要阻塞掛起,可以依靠資料庫實現。如讀鎖和寫鎖。都是在操作前加鎖。在java中,synchronized的思想也是悲觀鎖。

讀取頻繁使用樂觀鎖,寫入頻繁寫入樂觀鎖

樂觀鎖:總是認為不會產生併發問題,每次讀取資料的時候總認為不會有其他執行緒對資料庫進行修改,因此不會上鎖。
但是在更新時候會判斷在這之前有沒有對資料進行修改,一般會使用版本號機制,
version方式:一般是在資料表中加上一個資料庫的version機制。表示資料被修改的次數,當資料被修改時,version值會加一。。