何杰月c语言课程,多线程 - 何杰leo的个人空间 - OSCHINA - 中文开源技术交流社区...
多線程--百度百科:多線程(英語:multithreading),是指從軟件或者硬件上實現多個線程并發執行的技術。具有多線程能力的計算機因有硬件支持而能夠在同一時間執行多于一個線程,進而提升整體處理性能。具有這種能力的系統包括對稱多處理機、多核心處理器以及芯片級多處理(Chip-level multithreading)或同時多線程(Simultaneous multithreading)處理器。 [1] 在一個程序中,這些獨立運行的程序片段叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理(Multithreading)”。具有多線程能力的計算機因有硬件支持而能夠在同一時間執行多于一個線程(臺灣譯作“執行緒”),進而提升整體處理性能。 自己理解:線程是CPU處理數據的最小單位。一個程序可以使單線程也可以是多線程,如果是多線程,那么就執行的更快。 為什么多線程會執行的更快:在單位時間片中,高速運轉,切換線程。 1.在單位時間時間片上只能執行一個線程 2.CPU看到內存中有很多的線程,CPU在單位時間片(時間片:很微小的時間單位)上高速切換線程執行 CPU平均給線程分配資源,多線程就分配的更多資源 創建線程: 1.extends Tread public class PlayGameThread extends Thread{ public void run() { for (int i = 0; i < 100; i++) { System.out.println("double kill..."); } } } public class MusicThread extends Thread{ public void run() { for (int i = 0; i < 100; i++) { System.out.println("摩擦。。。摩擦..."); } } } public class Test { public static void main(String[] args) { PlayGameThread pgt = new PlayGameThread(); MusicThread mt = new MusicThread(); pgt.start(); mt.start(); } } 2.implement Runnable public class TicketThread implements Runnable{ private int num = 50; public void run() { // 最終的代碼 while(num>0){ System.out.println("您的票號是:"+num); num--; } } } public class Test { public static void main(String[] args) { /* * 只需要創建一個TicketThread的對象 tt * 以tt為參數來創建3個Thread對象 */ TicketThread tt = new TicketThread(); Thread t1 = new Thread(tt); Thread t2 = new Thread(tt); Thread t3 = new Thread(tt); t1.start(); t2.start(); t3.start(); } } Tread類中一些常用的方法: 1.sleep睡眠:線程類Thread當中有一個static void sleep(long millis)方法,在指定的毫秒數內讓當前正在執行的線程休眠。 2.優先級:線程的優先級:每個線程[線程對象]都有一個優先級,高優先級線程的執行優先于低優先級線程(簡單說:如果一個線程的優先級越高,獲得CPU資源的機會更大,不等于高優先級的就最先執行)。 3.守護線程: 1)、守護線程(精靈線程/后臺線程) ①每個線程都可以或不可以標記為一個守護程序 ②后臺線程僅僅就是對線程的一個分類或者標記 2)、特點: ① 一般來說后臺線程是為前臺線程服務的(例如gc線程); ② 如果所有的前臺線程都死了,那么后臺線程也會自動的死亡;但是前臺線程死了,后臺線程不一定立即死亡(可能還需要收尸...) ③ 一個線程的默認狀態和創建它的環境線程狀態一致 public static void main(String[] args) { Thread t = Thread.currentThread(); System.out.println(t.isDaemon()); t.setDaemon(true);//活動狀態的線程不能夠修改后臺線程 Thread tt = new Thread(); System.out.println(tt.isDaemon()); //tt.start();//活動的線程不能改變狀態Exception in thread "main" java.lang.IllegalThreadStateException tt.setDaemon(true); System.out.println(tt.isDaemon());//自定義線程未啟動可設置后臺線程 } 4.join等待終止:join為線程當中的方法,某線程實例調用該方法,其他線程會等待該線程執行完畢之后在執行。 5.禮讓yield:static?void yield() 暫停當前正在執行的線程對象,并執行其他線程。但是不一定會一定禮讓。 線程中經典的售票案例: 票池:50張。3個窗口售賣 1.票,用什么來存放票:票池 可以使用一個變量來表示票池,當賣出一個張票,該變量就自減一次 int num = 50; 2.本質就是要創建啟動線程(流程) 明確需要把什么事情封裝成獨立的線程對象 賣(一張)票的操作 怎么操作? 判斷是否有票,如果有票就賣一張 票總數減一 3.怎么實現: 自定義一個類 extends Thread類 實現功能自定義類覆寫Thread類當中的run方法,實現偽代碼功能 創建線程對象調用start方法啟動線程 1.共享問題,用來存放票量的,變量應該如何被多個窗口共享 2.應該自定義幾個類?1個類 之前游戲有不同功能,寫了不同類,賣票都是一個功能,所以定義一個類就行了 3.應該創建幾個對象?3個對象 三個窗口,可以創建三個對象來表示三個窗口 代碼實現: ①同步代碼塊 synchronized (mutex) { //需要被保護的代碼塊 } 實例: while(num>0){//只要有票就賣 synchronized (TicketThread.class) {//同步監聽,同一個對象 if(num > 0){//鎖住了此流程,從synchronized進入一個就關閉,等一個結束完了,然后又打開再進入第二個 System.out.println(getName()+"還剩的票數為:"+num); num--; } } } ②同步方法 public static synchronized void saleOne(){//加上synchronized為同步監聽方法,靜態方法!可加可不加根據需求 if(num>0){//賣一張票的操作【業務角度各自的】 System.out.println(Thread.currentThread().getName()+":您的票號是:"+num); num--; } } ③鎖機制 Lock 鎖定代碼塊,保護代碼塊 Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); } 實例: while(num>0){//只要有票就賣 lock.lock();//開啟鎖 try {//被保護的代碼 if(num>0){//賣一張票的操作【業務角度各自的】 System.out.println(getName()+":您的票號是:"+num); num--; } } finally {//釋放鎖,讓下一個進入 lock.unlock(); } } 在線程中的喚醒與等待:
Bank類//賬戶類 public class Bank { double qian; boolean empty = true;//true為空,則沒錢 void save(){ synchronized (Bank.class) {//要用同一個對象,那么就是使用同一個同步監聽 if(!empty){//當為false,那么就是有錢 //等待取錢先執行,直接讓synchronized中的代碼先不執行,執行另一個 try {//捕捉異常 Bank.class.wait();//表示前面用的對象,現在也在使用,在同一個對象下,使用同一個同步監聽, //并且等待和喚醒也是可以在同一個同步監聽中可以交替進行。 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("何杰存錢之前:"+qian); qian += 520;//此時為空,那么就存錢,對變量進行增 System.out.println("何杰存錢之后:"+qian); empty = false;//設置標識,當執行完存錢之后,那么現在就做一個標識,標識現在有錢 Bank.class.notify();//喚醒。使用對象去喚醒。當此程序執行完畢之后,喚醒另一個的程序 } } void get(){ synchronized (Bank.class) {//要用同一個對象,那么就是使用同一個同步監聽,Bank.class為本類的對象引用 if(empty){//當為true則沒錢,那么就要等待存錢執行 //等待,讓存錢先執行 try { Bank.class.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("王雨取錢之前:"+qian); qian -= 520;//此時為false,則是有錢,有錢了然后對變量進行減 System.out.println("王雨取錢之后:"+qian); empty = true;//上面進行的是false運算,當運行完畢時,那么就更改為沒錢,作為標識 Bank.class.notify(); } } } Save類//線程類 public class SaveMoney extends Thread { Bank bank; public SaveMoney(Bank bank) { this.bank = bank; } @Override public void run() { for (int i = 0; i < 20; i++) { bank.save(); } } } get類//線程類 public class GetMoney extends Thread { Bank bank; public GetMoney(Bank bank) { this.bank = bank; } @Override public void run() { for (int i = 0; i < 20; i++) { bank.get(); } } } Test類//測試類 public class Test {//測試類 public static void main(String[] args) { Bank bank = new Bank(); SaveMoney sav = new SaveMoney(bank); GetMoney get = new GetMoney(bank); sav.start(); get.start(); } } 線程的生命周期: ① 創建 ; 例如 Thread t = new Thread(); ② 就緒 ; 調用了start方法 t.start() ---> 告訴CPU我準備好了 ③ 運行 ; 獲得CPU的資源,開始執行線程體中的代碼 ④ 死亡 ; 有多種情況導致死亡, 1)例如線程體執行完畢(自然老死); 2)非自然死亡(異常沒有處理好); 3)對象失去引用 4)對象被垃圾回收機制銷毀 注意:① 休眠等操作可能導致正在運行的線程阻塞],阻塞完了(sleep完了)進入的是就緒狀態,相互一一直等待,出現死鎖! ② 一個線程死了就死了,不能夠死而復生 線程定時任務: Timer timer = new Timer(); MyTimerTask myTimerTask = new MyTimerTask(); //安排了 一個TimerTask 子類線程任務 timer.schedule(myTimerTask, new Date(),5000); Thread.sleep(8000); timer.cancel();//取消任務
總結
以上是生活随笔為你收集整理的何杰月c语言课程,多线程 - 何杰leo的个人空间 - OSCHINA - 中文开源技术交流社区...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言编写程序确定平年闰年,C语言平年闰
- 下一篇: 西凤秦韵酒52度多少钱?