多執行緒解決視窗售票問題
如果用過迅雷的人,就會發現,迅雷的速度比普通的下載器下載速度要快。是它有單用的網速通道嗎?當然不是,這是因為迅雷開啟了多執行緒,加快了下載速度。
什麼是程序?
程序就是正在執行的程式。開啟QQ就是開啟了一個程序,當一個程序進入記憶體執行,就變成了一個程序。程序是處於執行過程中的程式。
什麼是執行緒?
執行緒是程序中的一個執行單元,一個程序可以有多個執行緒。360安全衛士,在開啟病毒查殺的同時也可以開啟垃圾清理,一個程式開啟多個任務,也就是開啟多個執行緒的表現。
以前我們的CPU是單核的,執行緒不能同時進行,只能執行一個執行緒。所有執行緒輪流使用 CPU 的使用權,平均分配每個執行緒佔用 CPU 的時間。CPU會在各個程序之間高度切換。現在CPU有二核四核的,這樣就可以有多個執行緒同時程序。所以我們再看手機或電腦的時候,我們往往會關注是幾核的,多核的執行速度會比較快。
建立執行緒的目的:
是為了建立程式單獨執行的路徑,讓多部分程式碼實現同時執行。也就是說執行緒的建立並執行需要給定執行緒要執行的任務。
多執行緒定義方式:
1、定義類實現Runnable介面。2、覆蓋介面中的run方法。。
3、建立Thread類的物件
4、將Runnable介面的子類物件作為引數傳遞給Thread類的建構函式。
5、呼叫Thread類的start方法開啟執行緒。
這種方式去實現執行緒是比較好的,還有一種是繼承Thread類
1 定義一個類繼承Thread。
2 重寫run方法。
3 建立子類物件,就是建立執行緒物件。
4 呼叫start方法,開啟執行緒並讓執行緒執行,同時還會告訴jvm去呼叫run方法。
需求:電影院賣票,我們用多執行緒模擬電影院的賣票過程。假設有兩個視窗正在售票編號為01-100,視窗一和視窗二正在賣票,本次電影的座位共100個(本場電影只能賣100張票)編號為01-100,現在實現:1、兩個視窗賣票 2.計算兩個視窗各自賣了多少張票,各自賣的票的編號3.實現兩個視窗輪流賣票
public static void main(String[] args) { //有100張票 編號為01-100 List<String> li=new ArrayList<String>(); for (int i = 1; i <=100; i++) { if(i<10){ String s="0"+i; li.add(s); }else{ li.add(i+""); } } // tickets t=new tickets(); //建立兩個Thread類物件,傳遞Runnable介面實現類 tickets t=new tickets(li); //3.建立實現類物件 Thread t0 = new Thread(t,"視窗一"); //4.建立Thread類物件 ,並將runnable實現類作為引數 Thread t1=new Thread(t,"視窗二"); t0.start(); t1.start(); }
public class tickets implements Runnable { // 建立多執行緒的方式:1實現Runnable介面
private List<String> li; // 共享資料 票的編號01-100
private int ticket = 100; // 共享資料
// 利用建構函式載入初始資料
public tickets(List<String> li) {
this.li = li;
}
public tickets() {
super();
}// 空引數構造
@Override
public void run() { //2.重寫run方法
List<String> ticketNum =new ArrayList<String>();
int count = 0; // 區域性資料是定義各自的計數
while (true) { //
synchronized (this) { // 同步程式碼塊 這裡加了鎖 安全機制
if (ticket<=0) {
System.out.println(Thread.currentThread().getName() + "賣了" + count + "張,票的編號為:"+ticketNum);
return;
}
count++;
ticket--;
//---------------
Random ra=new Random();
int num = ra.nextInt(li.size()); //產生0-100的隨機數,作為索引
ticketNum.add(li.get(num)); //根據索引來取集合中的資料
li.remove(num); //因為取出來的票是不同的編號,取出一個就刪除一個,避免重複
//兩個程序交替執行
if(flag){
flag=true;
this.notify();//去喚醒另外一個程序
try {this.wait();} //本程序進行等待
catch (InterruptedException e) { e.printStackTrace();}
}else{
flag=false;
this.notify(); //去喚醒另一個程序
try {this.wait();} //本程序等待
catch (InterruptedException e) {e.printStackTrace();}
}
}
}
}
總結:其實生活中很多場景都可以執行到多執行緒,12306火車購票時我們可以網上購票,也可以視窗購票。執行緒是不安全的,但是速度快。我們加上同步程式碼塊的,加鎖機制後,保證了安全性,但是不可避免的降低速度。在Java中有很多類我們用的時候是不安全的,但是速度快。正是因為我們對於速度的考慮。