1. 程式人生 > >java 多執行緒(1)

java 多執行緒(1)

1.執行緒初始化new Thread(Runnable target,String name);一個實現了Runnable介面的類,注意extends Thread也自動實現了Runnable介面,name可有可無。

2.synchronized是對類的當前例項進行加鎖,防止其他執行緒同時訪問該類的該例項的所有synchronized塊,注意這裡是“類的當前例項”, 類的兩個不同例項就沒有這種約束了。那麼static synchronized就是類的class鎖,並不能鎖住物件鎖,只能鎖同樣為class的鎖

3.synchronized鎖程式碼塊可以加快效率,因為沒鎖的地方可以非同步執行,synchronized(this)等同於在方法上加synchronized,除了this,還可以鎖任意物件,一般是靜態變數及方法引數,通過鎖不同的物件,使得不同物件鎖之間可以非同步執行,大大提高效率

4.synchronized可重入鎖,異常釋放所有鎖

5.volatile的作用是強制從公共堆疊中取得變數的值,而不是從執行緒私有資料棧中取得變數的值,但volatile最致命的缺點是不支援原子性,只保證可見性,即多執行緒讀取共享變數時可以獲得最新值使用,但並不是執行緒安全的,synchronized也可以做到可見性,但synchronized效率低於volatile

6.java為每個object物件都實現了wait()和notify()方法,它們必須用在被synchronized同步的Object的臨界區內,否則報錯,wait()方法可以使呼叫改方法的執行緒釋放共享資源的鎖,然後從執行狀態推出,進入等待佇列,直到被再次喚醒,notify()方法可以隨時喚醒等待佇列中等待同一資源的一個執行緒,但並不釋放共享資源的鎖。生產者消費者:

import java.util.ArrayList;
import java.util.List;

class Product{
	private List<String> li=new ArrayList<>();
	synchronized void add() {
		while (li.size()>0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		li.add(""+Math.random());
		System.err.println(Thread.currentThread().getName()+" 增加了商品: "+li.get(li.size()-1));
		this.notifyAll();
	}
	synchronized void consume() {
		while (li.size()==0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.err.println(Thread.currentThread().getName()+" 消費了商品: "+li.get(li.size()-1));
		li.remove(li.size()-1);
		this.notifyAll();
	}
}
class P extends Thread{
	private Product product;
	P(Product product){
		this.product=product;
	}
	@Override
	public void run(){
		while (true) {
			product.add();
		}
	}
}
class C extends Thread{
	private Product product;
	C(Product product){
		this.product=product;
	}
	@Override
	public void run(){
		while (true) {
			product.consume();
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		Product product=new Product();
		Thread p1=new P(product);
		p1.setName("p1");
		Thread p2=new P(product);
		p2.setName("p2");
		Thread c1=new C(product);
		c1.setName("c1");
		Thread c2=new C(product);
		c2.setName("c2");
		p1.start();
		p2.start();
		c1.start();
		c2.start();
	}

}