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值會加一。。