小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

多線程/JAVA多線程 - 魔樂培訓 高端JAVA培訓 魔樂科技JAVA培訓

 smalllong 2010-10-30

多線程

 發(fā)布日期:2008-10-30 8:57:00 發(fā)布者:[IT電子教育門戶]   評論:[ 8]  瀏覽: 850

1、課程名稱:多線程
 多線程的基本作用、兩種實現(xiàn)的區(qū)別、同步與死鎖的概念。
 在開發(fā)中真正去編寫多線程代碼是很少的,要的只是基本概念,本章就是基本概念。
2、知識點
2.1、上次課程的主要知識點
 1、 包的定義及使用
 2、 四種訪問控制權(quán)限
2.2、本次預計講解的知識點
 1、 多線程的概念
 2、 多線程的兩種實現(xiàn)方式及區(qū)別
 3、 多線程的主要操作方法
 4、 同步與死鎖的概念
3、具體內(nèi)容
3.1、多線程的基本概念
 JAVA是少數(shù)幾個支持多線程的語言,所以多線程也就是成為了JAVA的一個特點。
 最早的DOS系統(tǒng)一旦有病毒進入,則立刻死機,因為在同一個時間段上,永遠只能有一個進程執(zhí)行。
 而windows就算是有病毒產(chǎn)生了,則系統(tǒng)照樣可以執(zhí)行。因為是屬于多進程的操作系統(tǒng)。
 進程:每一個應(yīng)用程序的啟動就稱為進程。
 線程:是在進程的基礎(chǔ)之上劃分出來的比進程更小的時間單位。
 線程的運行速度要超過進程。
 一個操作系統(tǒng)雖然可以跑多個進程,但是對于整個電腦而言只有一個CPU,所以在同一個時間段上CPU會處理多個程序,而在同一個時間點上CPU只會處理一個程序。
3.2、線程的實現(xiàn)
 在JAVA中要想實現(xiàn)一個多線程的程序有兩種方式:
  • 繼承Thread類
  • 實現(xiàn)Runnable接口
3.2.1、繼承Thread類實現(xiàn)
 一個類只要繼承了Thread類,那么此類就稱為多線程的操作類。
例如:以下代碼
class MyThread extends Thread{
};
 線程在操作之中應(yīng)該存在線程的主體,線程的主體方法為:run方法,所以Thread的子類必須覆寫run方法。
例如:以下代碼覆寫了run方法
class MyThread extends Thread{
 private String name ;
 public MyThread(String name){
  this.name = name ;
 }
 public void run(){
  for(int i=0;i<100;i++){
   System.out.println(name + "運行,i = " + i) ;
  }
 }
};
public class ThreadDemo01{
 public static void main(String args[]){
  MyThread mt1 = new MyThread("線程A ") ;
  MyThread mt2 = new MyThread("線程B ") ;
  mt1.run() ;
  mt2.run() ;
 }
};
 編譯并運行程序,觀察效果。從運行結(jié)果可以發(fā)現(xiàn),是A執(zhí)行完之后再執(zhí)行B,但是之前的程序并沒有同時運行,因為此時,線程并沒有啟動,如果要想啟動線程則必須調(diào)用Thread類中的start()方法才可以。例如:修改之前的代碼:
class MyThread extends Thread{
 private String name ;
 public MyThread(String name){
  this.name = name ;
 }
 public void run(){
  for(int i=0;i<100;i++){
   System.out.println(name + "運行,i = " + i) ;
  }
 }
};
public class ThreadDemo02{
 public static void main(String args[]){
  MyThread mt1 = new MyThread("線程A ") ;
  MyThread mt2 = new MyThread("線程B ") ;
  mt1.start() ;
  mt2.start() ;
 }
};
 發(fā)現(xiàn)此時的運行結(jié)果是,兩個線程之間交替執(zhí)行。
問題?
 既然start()方法調(diào)用的還是run方法,那為什么不直接調(diào)用run方法呢?
 觀察JDK中的Thread類實現(xiàn)
start()方法的定義:
    public synchronized void start() {
        if (started)
            throw new IllegalThreadStateException();
        started = true;
        start0();
    }
    private native void start0();
 如果一個線程已經(jīng)啟動了之后再啟動第二次,則會報非法的線程狀態(tài)。
 在JAVA中有一種技術(shù)稱為:JNI技術(shù),表示的是JAVA本地接口,可以通過JAVA調(diào)用本地操作系統(tǒng)中的函數(shù)支持。所以線程的實現(xiàn)靠的是操作系統(tǒng)的支持。
 如果一個多線程的操作,使用了Thread類來完成的話,那么此類就不能繼承其他的類了。
3.2.2、實現(xiàn)Runnable接口
 實現(xiàn)Rrnnable接口同時覆寫run方法
class MyThread implements Runnable{
 private String name ;
 public MyThread(String name){
  this.name = name ;
 }
 public void run(){
  for(int i=0;i<100;i++){
   System.out.println(name + "運行,i = " + i) ;
  }
 }
};
 但是Runnable接口與Thread類不同的是,Runnable接口中并沒有關(guān)于start()方法的定義,而只有Thread類中才有。繼續(xù)觀察Thread類。
 觀察Thread類中有如下兩個構(gòu)造方法:
  • public Thread(Runnable target)
• public Thread(Runnable target,String name)
例如:使用以上的操作啟動多線程
class MyThread implements Runnable{
 private String name ;
 public MyThread(String name){
  this.name = name ;
 }
 public void run(){
  for(int i=0;i<100;i++){
   System.out.println(name + "運行,i = " + i) ;
  }
 }
};
public class ThreadDemo03{
 public static void main(String args[]){
  MyThread mt1 = new MyThread("線程A ") ;
  MyThread mt2 = new MyThread("線程B ") ;
  new Thread(new MyThread("線程A")).start() ;
  new Thread(new MyThread("線程B")).start() ;
 }
};
3.2.3、Thread類與Runnable接口的關(guān)系
 1、 Thread也是Runnable接口的子類
  • public class Thread extends Object implements Runnable
 2、 Thread類中有單繼承的局限,而Runnable中并沒有此局限
 3、 使用Runnable實現(xiàn)的多線程操作類,適合于多個線程對象共享數(shù)據(jù)
例如:驗證資源的共享
A、 使用Thread類完成
class MyThread extends Thread{
 private int ticket = 10 ;
 public void run(){
  for(int i=0;i<100;i++){
   if(ticket>0){
    System.out.println("賣票。ticket = " + ticket--) ;
   }
  }
 }
};
public class ThreadDemo04{
 public static void main(String args[]){
  MyThread mt1 = new MyThread() ;
  MyThread mt2 = new MyThread() ;
  MyThread mt3 = new MyThread() ;
  mt1.start() ;
  mt2.start() ;
  mt3.start() ;
 }
};
 整個程序一共賣出了30張票,但是實際上只有10張票,這是因為每一個線程對象都擁有各自的10張票。而如果現(xiàn)在使用Runnable接口實現(xiàn)的話,則可以達到資源的共享
B、 使用Runnable接口實現(xiàn)
class MyThread implements Runnable{
 private int ticket = 10 ;
 public void run(){
  for(int i=0;i<100;i++){
   if(ticket>0){
    System.out.println("賣票。ticket = " + ticket--) ;
   }
  }
 }
};
public class ThreadDemo05{
 public static void main(String args[]){
  MyThread mt = new MyThread() ;
  new Thread(mt).start() ;
  new Thread(mt).start() ;
  new Thread(mt).start() ;
 }
};
3.3、線程的狀態(tài)
 
 所有的線程雖然在語句上有先有后,但是是同時啟動的,誰先搶占到CPU資源,誰就運行。
 線程創(chuàng)建完成之后,等待啟動,啟動之前先進入到就緒狀態(tài)。之后等待CPU調(diào)度,調(diào)度之后進入運行狀態(tài)。
 如果中間有問題了,導致程序暫停執(zhí)行,則進入到阻塞狀態(tài)?;氐骄途w狀態(tài),等待再次執(zhí)行。
 當全部程序執(zhí)行完之后,就進入到終止狀態(tài)了。
 所有的線程并不是一調(diào)用start()方法就立刻啟動,而是要等待CPU調(diào)度才可以執(zhí)行。
3.4、線程的主要操作方法
 線程中的所有操作方法都是在Thread類中定義的。
3.4.1、取得當前正在運行的線程名稱
 在Thread類中有以下一個方法可以取得當前正在運行的線程對象。
  • public static Thread currentThread()
 Thread類的構(gòu)造方法:
  • public Thread(Runnable target,String name)
• public Thread(String name)
 取得線程的名稱:public final String getName()
 設(shè)置線程的名稱:public final void setName(String name)
 可以通過Thread類中的setName()方法設(shè)置一個線程的名稱,但是最好在線程啟動之前進行設(shè)置。
例如:以下代碼取得了當前正在運行的線程名稱
class MyThread implements Runnable{
 public void run(){
  for(int i=0;i<10;i++){
    System.out.println(Thread.currentThread().getName() + "運行, i = " + i) ;
  }
 }
};
public class ThreadDemo06{
 public static void main(String args[]){
  MyThread mt = new MyThread() ;
  new Thread(mt).start() ;
  new Thread(mt).start() ;
  new Thread(mt).start() ;
 }
};
 發(fā)現(xiàn)此時線程的名稱很有規(guī)律:Thread-0、Thread-1、Thread-2,…
 里面肯定有一個static的屬性,用于保存當前產(chǎn)生了多少個對象。
例如:直接為線程命名
class MyThread implements Runnable{
 public void run(){
  for(int i=0;i<10;i++){
    System.out.println(Thread.currentThread().getName() + "運行, i = " + i) ;
  }
 }
};
public class ThreadDemo07{
 public static void main(String args[]){
  MyThread mt = new MyThread() ;
  new Thread(mt,"線程A").start() ;
  new Thread(mt,"線程B").start() ;
  new Thread(mt,"線程C").start() ;
  new Thread(mt).start() ;
  new Thread(mt).start() ;
 }
};
分析以下程序的執(zhí)行結(jié)果:
class MyThread implements Runnable{
 public void run(){
  for(int i=0;i<10;i++){
    System.out.println(Thread.currentThread().getName() + "運行, i = " + i) ;
  }
 }
};
public class ThreadDemo08{
 public static void main(String args[]){
  MyThread mt = new MyThread() ;
  new Thread(mt,"線程").start() ;
  mt.run() ;  ? 主方法直接調(diào)用的run()方法
 }
};
 觀察輸出結(jié)果:
  • 發(fā)現(xiàn)有一個main線程的存在。
 一個JAVA程序至少啟動幾個線程?是兩個
  • MAIN:主線程
  • 垃圾收集線程
3.4.2、線程的休眠
 對于線程可以允許其稍微暫停運行,使用休眠的語法即可完成,方法定義如下:
  • public static void sleep(long millis) throws InterruptedException
  • 此方法會拋出中斷異常
例如:以下程序驗證了sleep()方法的使用
class MyThread implements Runnable{
 public void run(){
  for(int i=0;i<10;i++){
   try{
    Thread.sleep(500) ;
   }catch(Exception e){}
   System.out.println(Thread.currentThread().getName() + "運行, i = " + i) ;
  }
 }
};
public class ThreadDemo09{
 public static void main(String args[]){
  MyThread mt = new MyThread() ;
  new Thread(mt,"線程").start() ;
  mt.run() ;
 }
};
3.4.3、線程的中斷
 之前休眠方法上有一個中斷的異常拋出,實際上線程是可以中斷的。
 如果要想中斷一個線程則必須使用另外一個線程控制,中斷線程的方法:
  • public void interrupt()
例如:以下代碼演示了中斷線程的操作
class MyThread implements Runnable{
 public void run(){
  System.out.println("********* 進入run方法 **********") ;
  try{
   System.out.println(" =========== 開始休眠 ===============") ;
   Thread.sleep(20000) ; 
   System.out.println(" =========== 結(jié)束休眠 ===============") ;
  }catch(Exception e){
   System.out.println(e) ;
   // 表示直接返回到方法的調(diào)用處
   return ;
  }
  System.out.println("********* 完成run方法 **********") ;
 }
};
public class ThreadDemo10{
 public static void main(String args[]){
  MyThread mt = new MyThread() ;
  Thread t = new Thread(mt,"線程") ;
  t.start() ;
  try{
   // 為了可以讓程序多休眠一會兒
   Thread.sleep(1000) ; 
  }catch(Exception e){
  }
  // 中斷線程執(zhí)行
  t.interrupt() ;
 }
};
3.4.4、線程的強制執(zhí)行
 可以使用一個方法讓一個線程強制的執(zhí)行下去。方法的定義為:
  • public final void join() throws InterruptedException
例如:以下代碼演示了join的作用
class MyThread implements Runnable{
 public void run(){
  int i = 0 ;
  while(true){
   System.out.println(Thread.currentThread().getName() + " --> i = " + i++) ;
  }
 }
};
public class ThreadDemo11{
 public static void main(String args[]){
  Thread t = new Thread(new MyThread(),"==線程==") ;
  int i = 0 ;
  t.start() ;
  while(true){
   if(i>=100){
    // 強制運行
    try{
     t.join() ;
    }catch(Exception e){}
   }
   System.out.println("MAIN " + i++) ;
  }
 }
};
3.5、線程的同步與死鎖

4、總結(jié)
1、 線程可以不掌握代碼,但是所有的概念必須非常清楚
2、 進程與線程的區(qū)別
 • 線程是在進程的基礎(chǔ)之上的進一步劃分
 • 如果沒有進程了,則線程也不存在
3、 JAVA中線程實現(xiàn)的兩種方式
 • 繼承Thread類,不能共享數(shù)據(jù)
 • 實現(xiàn)Runnable接口,可以共享數(shù)據(jù)
 • 使用Runnable的最大好處是可以避免單繼承帶來的局限
4、 JAVA中一個java命令實際上啟動的是一個JVM進程,一個JVM進程至少啟動兩個線程:
 • MAIN線程
 • GC線程
5、 線程的主要操作方法
 • currentThread()、getName()、sleep()

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多