???????? 多線程學習
?* 程序,進程和線程
程序: 是指計算機指令的集合,它以文件的形式存儲在磁盤上。
進程: 是一個程序在其自身的地址空間中的一次執行活動。
進程是資源的申請,調度和獨立運行的單位,因此,它使用系統中的運行資源;而程序不能申請
系統資源,不能被系統調度,也不能作為獨立運行的單位,因此,它不站用系統的運行資源。
線程: 是進程中一個單一的連接控制流程。一個進程可以有多個線程。
線程又稱為輕量級進程,它和進程一樣擁有獨立的執行控制,由操作系統負責調度,區別在于線程
沒有獨立的存儲空間,而是和所屬進程中的其它線程共享一個存儲空間,這使得線程間的通信遠
較進程簡單。
?* Java對多線程的支持
Java在語言級提供了對多線程程序設計的支持。
實現線程程序的兩種方式:
(1)從Thread類繼承;
(2)實現Runnable接口。
Java運行時系統實現了一個用于調度線程執行的線程調度器,用于確定某一時刻由哪一個線程在
CPU上運行。
在java技術中,線程通常是搶占式的而不需要時間片分配進程(分配給每個線程相等的CPU時間的
進程)。搶占式調度模型就是許多線程處于可以運行狀態(等待狀態),但實際上只有一個線程在
運行。該線程一直運行到它終止進入可運行狀態(等待狀態),或者另一個具有更高優級的線程
變成可運行狀態。在后一種情況下,低優先級的線程被高優先級的線程搶占,高優先級的線程獲得
運行的機會。
Java線程調度器支持不同優先級線程的搶占方式,但其本身不支持相同優先級線程的時間片輪換。
Java運行時系統所在的操作系統(例如:windows2000)支持時間片的輪換,則線程調度器就支持
相同優先級線程的時間片輪換。
用多線程技術模擬一個售票系統
實現代碼如下:
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)? //同步塊在關鍵字后得加個對象(任意的對象都可以)
??? {
???? ?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"。
?同步的兩種方式:同步塊和同步方法
?沒一個對象都有一個監視器(monitor),或者叫做瑣。
?同步方法利用的是this所代表的對象的瑣。
?每個class也有一個瑣,是這個class所對應的Class對象的瑣。
完整示例:
class TicketSystem
{
?public static void main(String[] args)
?{
??SellTicket st = new SellTicket();
??new Thread(st).start();
??/*
?? *寫一個try{}catch{}塊讓main()方法所在的線程睡1秒
?? *主要是想要線程優先啟動
??*/
??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)? //同步塊在關鍵字后得加個對象(任意的對象都可以)
??? {
???? ?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--;????
???? } ??
?}
}
?* 線程的死瑣
?哲學家進餐的問題
?一幫哲學家在一起進餐,但是每個人都只有1支筷子,大家都在等待別人拿出一支筷子讓自己
?先吃,然后再把自己的拿出去,但是大家都不愿意拿出自己的筷子。
?線程1瑣住了對象A的監視器,等待對象B的監視器,線程2鎖住了對象B的監視器,等待對象A的
?監視器,就造成了死瑣。
?示例代碼:
class TicketSystem
{
?public static void main(String[] args)
?{
??SellTicket st = new SellTicket();
??new Thread(st).start();
??/*
?? *寫一個try{}catch{}塊讓main()方法所在的線程睡1秒
?? *主要是想要線程優先啟動
??*/
??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)? //同步塊在關鍵字后得加個對象(任意的對象都可以)
??? {
?????? 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
?每個對象除了有一個瑣之外,還有一個等待隊列(wait set),當一個對象剛剛創建的時候,它
?的等待隊列是空的。
?我們應該在當前線程鎖住對象的瑣后,去調用該對象的wait方法。
?當調用對象的notify方法時,將從該對象的等待隊列中刪除一個任意的線程,這個線程將再次
?成為可運行的線程。
?當調用對象的notifyAll方法時,將從該對象的等待隊列中刪除所有等待的線程,這些線程將
?成為可運行的線程。
?wait和notify重要用于producer-consumer這種關系中。
?代碼示例:
?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?? //生產者
{
?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?? //消費者
{
?Queque q;
?Consumer(Queque q)
?{
??this.q=q;
?}
?public void run()
?{
??while(true)
??{
???System.out.println("Consumer get"+q.get());
??}
?}
}
class Queque??? //放置數據
{
?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;
?}
}
?線程的狀態圖
?? |
?? | new Thread
?? |?????????????????? yield????? sleep,wait,suspend,I/O阻塞
? \|/ start???????????????????? |------------------------------------>|
? New----->Runnable|??????????????????????????????????????????????????????? |Not Runnable
??????????????????????????? \??? |<------------------------------------|??????? ?/
???????????????????????????? \???? sleep結束,notify,resume,I/O操作完成??? /
????????????????????????????? \??????????????????????????????????????????????????????????????? ?/
?????????????????????????????? \???????????????????????????????????????????????????????????? ?/
??????????????????????????????? \??????????????????????????????????????????????????????? ?? /
???????????????????????????????? \?????????????????????????????????????????????????????? ? /
????????????????????????????????? \ run方法退出?????????????????????????????? ?/
?????????????????????????????????? \stop方法調用??????????????????????????? ?/
??????????????????????????????????? \?????????????????????????????????????????????? ?/
???????????????????????????????????? \?????????????????????????????????????????? ? /?
????????????????????????????????????? \??????????????????????????????????????? ? /? stop方法調用
?????????????????????????????????????? \????????????????????????????????????? ?/
??????????????????????????????????????? \???????????????????????????????????? /
???????????????????????????????????????? \?????????????????????????????????? /
????????????????????????????????????????? \?????????????????????????????? ?/
?????????????????????????????????????????? \????????????????????????? ?? /
??????????????????????????????????????????? \????????????????????????? ?/
???????????????????????????????????????????? \ ______?_____/
????????????????????????????????????????????? |??? ? Dead?????? ??|
????????????????????????????????????????????? |____________|
?線程的終止
?
?設置一個flag變量。
?結合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;
?}
}