???????? 多線程學(xué)習(xí)
?* 程序,進(jìn)程和線程
程序: 是指計(jì)算機(jī)指令的集合,它以文件的形式存儲(chǔ)在磁盤上。
進(jìn)程: 是一個(gè)程序在其自身的地址空間中的一次執(zhí)行活動(dòng)。
進(jìn)程是資源的申請(qǐng),調(diào)度和獨(dú)立運(yùn)行的單位,因此,它使用系統(tǒng)中的運(yùn)行資源;而程序不能申請(qǐng)
系統(tǒng)資源,不能被系統(tǒng)調(diào)度,也不能作為獨(dú)立運(yùn)行的單位,因此,它不站用系統(tǒng)的運(yùn)行資源。
線程: 是進(jìn)程中一個(gè)單一的連接控制流程。一個(gè)進(jìn)程可以有多個(gè)線程。
線程又稱為輕量級(jí)進(jìn)程,它和進(jìn)程一樣擁有獨(dú)立的執(zhí)行控制,由操作系統(tǒng)負(fù)責(zé)調(diào)度,區(qū)別在于線程
沒有獨(dú)立的存儲(chǔ)空間,而是和所屬進(jìn)程中的其它線程共享一個(gè)存儲(chǔ)空間,這使得線程間的通信遠(yuǎn)
較進(jìn)程簡(jiǎn)單。
?* Java對(duì)多線程的支持
Java在語(yǔ)言級(jí)提供了對(duì)多線程程序設(shè)計(jì)的支持。
實(shí)現(xiàn)線程程序的兩種方式:
(1)從Thread類繼承;
(2)實(shí)現(xiàn)Runnable接口。
Java運(yùn)行時(shí)系統(tǒng)實(shí)現(xiàn)了一個(gè)用于調(diào)度線程執(zhí)行的線程調(diào)度器,用于確定某一時(shí)刻由哪一個(gè)線程在
CPU上運(yùn)行。
在java技術(shù)中,線程通常是搶占式的而不需要時(shí)間片分配進(jìn)程(分配給每個(gè)線程相等的CPU時(shí)間的
進(jìn)程)。搶占式調(diào)度模型就是許多線程處于可以運(yùn)行狀態(tài)(等待狀態(tài)),但實(shí)際上只有一個(gè)線程在
運(yùn)行。該線程一直運(yùn)行到它終止進(jìn)入可運(yùn)行狀態(tài)(等待狀態(tài)),或者另一個(gè)具有更高優(yōu)級(jí)的線程
變成可運(yùn)行狀態(tài)。在后一種情況下,低優(yōu)先級(jí)的線程被高優(yōu)先級(jí)的線程搶占,高優(yōu)先級(jí)的線程獲得
運(yùn)行的機(jī)會(huì)。
Java線程調(diào)度器支持不同優(yōu)先級(jí)線程的搶占方式,但其本身不支持相同優(yōu)先級(jí)線程的時(shí)間片輪換。
Java運(yùn)行時(shí)系統(tǒng)所在的操作系統(tǒng)(例如:windows2000)支持時(shí)間片的輪換,則線程調(diào)度器就支持
相同優(yōu)先級(jí)線程的時(shí)間片輪換。
用多線程技術(shù)模擬一個(gè)售票系統(tǒng)
實(shí)現(xiàn)代碼如下:
class TicketSystem
{
?public static void main(String[] args)
?{
??SellTicket st = new SellTicket();
??new Thread(st).start();
??new Thread(st).start();
??new Thread(st).start();
??new Thread(st).start();
?}
}
class SellTicket implements Runnable
{
?int tickets=100;
?Object o = new Object();
?public void run()
?{
??while(true)
??{
???/*
??? synchronized(o)? //同步塊在關(guān)鍵字后得加個(gè)對(duì)象(任意的對(duì)象都可以)
??? {
???? ?if(tickets>0)
??? ?{
?????? try
????? {
???? ??? Thread.sleep(10);
????? }
????? catch(Exception e)
????? {
??????? e.printStackTrace();
????? }
????????? System.out.println(Thread.currentThread().getName()+
????????? "sell tickets"+tickets);
????????? tickets--;????
???? }
??? }
??? */
??? sell();?
??}
?}
?public synchronized void sell()? //同步方法
?{
???? ?if(tickets>0)
??? ?{
?????? try
????? {
???? ??? Thread.sleep(10);
????? }
????? catch(Exception e)
????? {
??????? e.printStackTrace();
????? }
????????? System.out.println(Thread.currentThread().getName()+
????????? "sell tickets"+tickets);
????????? tickets--;????
???? } ??
?}
}
?* 線程的同步
?The code segments within a program that access the same object from separate,concurrent
?thread are called "critical sections"。
?同步的兩種方式:同步塊和同步方法
?沒一個(gè)對(duì)象都有一個(gè)監(jiān)視器(monitor),或者叫做瑣。
?同步方法利用的是this所代表的對(duì)象的瑣。
?每個(gè)class也有一個(gè)瑣,是這個(gè)class所對(duì)應(yīng)的Class對(duì)象的瑣。
完整示例:
class TicketSystem
{
?public static void main(String[] args)
?{
??SellTicket st = new SellTicket();
??new Thread(st).start();
??/*
?? *寫一個(gè)try{}catch{}塊讓main()方法所在的線程睡1秒
?? *主要是想要線程優(yōu)先啟動(dòng)
??*/
??try
??{
???Thread.sleep(1);
??}
??catch(Exception e)
??{
???e.printStackTrace();
??}
??st.b=true;
??new Thread(st).start();
??//new Thread(st).start();
??//new Thread(st).start();
?}
}
class SellTicket implements Runnable
{
?int tickets=100;
?Object obj = new Object();
?boolean b=false;
?public void run()
?{
??if(b==false)
??{
???while(true)
????? sell();
??}
??else
??{
?????while(true)
?? {??
??? synchronized(this)? //同步塊在關(guān)鍵字后得加個(gè)對(duì)象(任意的對(duì)象都可以)
??? {
???? ?if(tickets>0)
??? ?{
?????? try
????? {
???? ??? Thread.sleep(10);
????? }
????? catch(Exception e)
????? {
??????? e.printStackTrace();
????? }
????????? System.out.println("obj:"+Thread.currentThread().getName()+
????????? " sell tickets"+tickets);
????????? tickets--;????
???? }
??? }???
?? // sell();?
??}
??}
?}
?public synchronized void sell()? //同步方法
?{
???? ?if(tickets>0)
??? ?{
?????? try
????? {
???? ??? Thread.sleep(10);
????? }
????? catch(Exception e)
????? {
??????? e.printStackTrace();
????? }
????????? System.out.println("sell():"+Thread.currentThread().getName()+
????????? "sell tickets"+tickets);
????????? tickets--;????
???? } ??
?}
}
?* 線程的死瑣
?哲學(xué)家進(jìn)餐的問題
?一幫哲學(xué)家在一起進(jìn)餐,但是每個(gè)人都只有1支筷子,大家都在等待別人拿出一支筷子讓自己
?先吃,然后再把自己的拿出去,但是大家都不愿意拿出自己的筷子。
?線程1瑣住了對(duì)象A的監(jiān)視器,等待對(duì)象B的監(jiān)視器,線程2鎖住了對(duì)象B的監(jiān)視器,等待對(duì)象A的
?監(jiān)視器,就造成了死瑣。
?示例代碼:
class TicketSystem
{
?public static void main(String[] args)
?{
??SellTicket st = new SellTicket();
??new Thread(st).start();
??/*
?? *寫一個(gè)try{}catch{}塊讓main()方法所在的線程睡1秒
?? *主要是想要線程優(yōu)先啟動(dòng)
??*/
??try
??{
???Thread.sleep(1);
??}
??catch(Exception e)
??{
???e.printStackTrace();
??}
??st.b=true;
??new Thread(st).start();
??//new Thread(st).start();
??//new Thread(st).start();
?}
}
class SellTicket implements Runnable
{
?int tickets=100;
?Object obj = new Object();
?boolean b=false;
?public void run()
?{
??if(b==false)
??{
???while(true)
????? sell();
??}
??else
??{
?????while(true)
?? {??
??? synchronized(obj)? //同步塊在關(guān)鍵字后得加個(gè)對(duì)象(任意的對(duì)象都可以)
??? {
?????? try
????? {
???? ??? Thread.sleep(10);
????? }
????? catch(Exception e)
????? {
??????? e.printStackTrace();
????? }?
????? synchronized(this)
????? { ??? ?
???? ?????? if(tickets>0)
??? ???????? {
??????????????? System.out.println("obj:"+Thread.currentThread().getName()+
??????????????? " sell tickets"+tickets);
??????????????? tickets--;????
????????????? }
????? }
????? }???
??? }
??}
?}
?public synchronized void sell()? //同步方法
?{
??synchronized(obj)
??{
???? ?if(tickets>0)
??? ?{
?????? try
????? {
???? ??? Thread.sleep(10);
????? }
????? catch(Exception e)
????? {
??????? e.printStackTrace();
????? }
????????? System.out.println("sell():"+Thread.currentThread().getName()+
????????? "sell tickets"+tickets);
????????? tickets--;????
???? }
??}?
?}
}
?* wait,notify,notifyAll
?每個(gè)對(duì)象除了有一個(gè)瑣之外,還有一個(gè)等待隊(duì)列(wait set),當(dāng)一個(gè)對(duì)象剛剛創(chuàng)建的時(shí)候,它
?的等待隊(duì)列是空的。
?我們應(yīng)該在當(dāng)前線程鎖住對(duì)象的瑣后,去調(diào)用該對(duì)象的wait方法。
?當(dāng)調(diào)用對(duì)象的notify方法時(shí),將從該對(duì)象的等待隊(duì)列中刪除一個(gè)任意的線程,這個(gè)線程將再次
?成為可運(yùn)行的線程。
?當(dāng)調(diào)用對(duì)象的notifyAll方法時(shí),將從該對(duì)象的等待隊(duì)列中刪除所有等待的線程,這些線程將
?成為可運(yùn)行的線程。
?wait和notify重要用于producer-consumer這種關(guān)系中。
?代碼示例:
?class Test
{
?public static void main(String[] args)
?{
??Queque q = new Queque();
??Procedur p = new Procedur(q);
??Consumer c = new Consumer(q);
??p.start();
??c.start();
??
?}
}
class Procedur extends Thread?? //生產(chǎn)者
{
?Queque q;
?Procedur(Queque q)
?{
??this.q=q;
?}
?public void run()
?{
??for(int i=0;i<10;i++)
??{
???q.put(i);
???System.out.println("Procedur put"+ i);
??}
?}
}
class Consumer extends Thread?? //消費(fèi)者
{
?Queque q;
?Consumer(Queque q)
?{
??this.q=q;
?}
?public void run()
?{
??while(true)
??{
???System.out.println("Consumer get"+q.get());
??}
?}
}
class Queque??? //放置數(shù)據(jù)
{
?int value;
?boolean bFull=false;
?public synchronized void put(int i)
?{
??if(!bFull)
??{
??? value=i;?
??? bFull=true;
??? notify();??
??}
??try
??{
???wait();
??}
??catch(Exception e)
??{
???e.printStackTrace();
??}
?}
?public synchronized int get()
?{
??if(!bFull)
??{
???try
???{
????wait();
???}
???catch(Exception e)
???{
????e.printStackTrace();
???}
??}
??bFull=false;
??notify();
??return value;
?}
}
?線程的狀態(tài)圖
?? |
?? | new Thread
?? |?????????????????? yield????? sleep,wait,suspend,I/O阻塞
? \|/ start???????????????????? |------------------------------------>|
? New----->Runnable|??????????????????????????????????????????????????????? |Not Runnable
??????????????????????????? \??? |<------------------------------------|??????? ?/
???????????????????????????? \???? sleep結(jié)束,notify,resume,I/O操作完成??? /
????????????????????????????? \??????????????????????????????????????????????????????????????? ?/
?????????????????????????????? \???????????????????????????????????????????????????????????? ?/
??????????????????????????????? \??????????????????????????????????????????????????????? ?? /
???????????????????????????????? \?????????????????????????????????????????????????????? ? /
????????????????????????????????? \ run方法退出?????????????????????????????? ?/
?????????????????????????????????? \stop方法調(diào)用??????????????????????????? ?/
??????????????????????????????????? \?????????????????????????????????????????????? ?/
???????????????????????????????????? \?????????????????????????????????????????? ? /?
????????????????????????????????????? \??????????????????????????????????????? ? /? stop方法調(diào)用
?????????????????????????????????????? \????????????????????????????????????? ?/
??????????????????????????????????????? \???????????????????????????????????? /
???????????????????????????????????????? \?????????????????????????????????? /
????????????????????????????????????????? \?????????????????????????????? ?/
?????????????????????????????????????????? \????????????????????????? ?? /
??????????????????????????????????????????? \????????????????????????? ?/
???????????????????????????????????????????? \ ______?_____/
????????????????????????????????????????????? |??? ? Dead?????? ??|
????????????????????????????????????????????? |____________|
?線程的終止
?
?設(shè)置一個(gè)flag變量。
?結(jié)合interrupt()方法。
?code:
class TestThread
{
?public static void main(String[] args)
?{
??Thread1 t1=new Thread1();
??t1.start();
??int index=0;
??while(true)
??{
???if(index++==500)
???{
????t1.stopThread();
????break;
???}
???System.out.println(Thread.currentThread().getName());
??}
?}
}
class Thread1 extends Thread
{
?private boolean bStop=false;
?public void run()
?{
??while(!bStop)
??{
???System.out.println(getName());
??}
?}
?public void stopThread()
?{
??bStop=true;
?}
}