線程是一個程式内部的順序控制流。
線程和程序的差別:
每個程序都有獨立的代碼和資料空間(程序上下文),程序間的切換會有較大的開銷。
線程可以看成是輕量級的程序,同一類線程共享代碼和資料空間,每個線程有獨立的運作棧和程式計數器(pc),線程切換的開銷小。
多程序:在作業系統中能同時運作多個任務(程式)
多線程:在同一應用程式中有多個順序流同時執行
當多線程sleep時,如何停止呢?
1、interrupt()方法,這個方法很粗暴不建議使用,這個相當于睡覺的時候一盆涼水潑下來,會抛出interruptedexception。
2、stop()方法,已經廢棄了,這個比interrupt更粗暴,直接停止線程。不建議使用。
3、用标量在外部控制。
join方法:合并某個線程。把處于并行運作狀态的線程合并到目前線程中。
yield()方法:讓出cpu,給其他線程執行的機會。
setpriority():設定優先級,優先級越高,cpu分得時間片就越多,越容易得到執行。
線程同步:在java語言中,引入了對象互斥鎖的概念,保證共享資料操作的完整性。每個對象都對應于一個可稱為“互斥鎖”的标記。這個标記保證在任何一個時刻,隻能有一個線程通路該對象。
關鍵字synchronized來與對象的互斥鎖聯系。當某個對象synchronized修飾時,表明該對象在任一時刻隻能由一個線程通路。synchronized可以作為關鍵字設在方法上,也可以使用synchronized(this){}中表明鎖定該對象的内容。
盡量隻鎖定一個對象,避免死鎖。
當一個線程鎖定了一個方法的時候,其他線程可以通過其他方法修改值,是以,一定要保證所有有關這個變量的方法都要加鎖。
同步執行個體:
<span style="font-family:microsoft yahei;"><span style="font-size:12px;">package thread;
public class tt implements runnable{
int b = 100 ;
@override
public void run() {
m1() ;
}
//隻會鎖定m1方法内的内容,不會鎖定b
public synchronized void m1() {
b = 1000 ;
try {
thread.sleep(5000);
} catch (interruptedexception e) {
e.printstacktrace();
}
system.out.println("b = " + b);
public void m2() {
system.out.println(b);
public static void main(string[] args) {
tt t = new tt() ;
thread thread = new thread(t) ;
thread.start() ;
thread.sleep(1000);
t.m2();
}
</span></span>
生産者與消費者執行個體:
<span style="font-family:microsoft yahei;">package thread;
public class producerconsumer {
syncstack ss = new syncstack() ;
producer p = new producer(ss) ;
consumer c = new consumer(ss) ;
new thread(p).start();
new thread(c).start();
class wotou {
int id ;
wotou(int id) {
this.id = id ;
public string tostring() {
return "id = " + this.id ;
class syncstack {
int index = 0 ;
wotou[] arrwt = new wotou[6] ;
public synchronized void push(wotou wt) {
while(index == arrwt.length) {
try {
this.wait();
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
this.notify();
arrwt[index] = wt ;
index ++ ;
public synchronized wotou pop() {
while(index == 0) {
index -- ;
return arrwt[index] ;
class producer implements runnable {
syncstack s = null ;
public producer(syncstack s) {
this.s = s ;
for(int i=0; i<20; i++) {
wotou wt = new wotou(i) ;
system.out.println("push : " + wt);
s.push(wt);
class consumer implements runnable {
public consumer(syncstack s) {
wotou wt = s.pop() ;
system.out.println("pop : " + wt);
}</span>
wait和sleep的差別
wait時别的線程可以通路鎖定對象,調用wait方法的時候必須鎖定該對象。sleep時别的線程也不可以通路鎖定對象。