多線程基礎及實例(java)


前言:
每個正在系統上運行的程序都是一個進程。每個進程包含一到多個線程。 線程是一組指令的集合,或者是程序的特殊段,它可以在程序里獨立執行。也可以把它理解為代碼運行的上下文。所以線程基本上是輕量級的進程,它負責在單個程序里執行多任務。通常由操作系統負責多個線程的調度和執行。
 
使用線程可以把占據時間長的程序中的任務放到后台去處理,程序的運行速度可能加快,在一些等待的任務實現上如用戶輸入、文件讀寫和網絡收發數據等,線程就比較有用了。在這種情況下可以釋放一些珍貴的資源如內存占用等等。

如果有大量的線程,會影響性能,因為操作系統需要在它們之間切換,更多的線程需要更多的內存空間,線程的中止需要考慮其對程序運行的影響。通常塊模型數據是在多個線程間共享的,需要防止線程死鎖情況的發生。
 
正文:

兩種實現多線程的方式,繼承Thread類或者實現Runnable接口。

繼承 Thread類 :
package  com.zsz.thread;
 
public  class  MyThread  extends  Thread {
     
      private  int  index ;
     
      public  MyThread(  int  index){
             this .  index  = index;
     }
      public  void  run () { 
           
             for (  int  i=0;i<5;i++){
                System.  out .println(  index +  ":" +i);
           }
     } 
      public  static  void  main(String[] args){
           MyThread MyThread =  new  MyThread(1);
           MyThread MyThread2 =  new  MyThread(2);
           MyThread.start();
           MyThread2.start();
     }
}
可能的運行結果:
1:0
2:0
1:1
2:1
1:2
2:2
1:3
2:3
1:4
2:4
由於執行CPU占用時間被切換,線程狀態的切換,導致執行順序的不同。
 
實現 Runnable接口:
package  com.zsz.thread;
 
public  class  MyRunnable  implements  Runnable{
 
      private  int  index ;
     
      public  MyRunnable(  int  index){
             this .  index  = index;
     }
      @Override
      public  void  run() {
             for (  int  i=0;i<5;i++){
                System.  out .println(  index +  ":" +i);
           }
     }
     
      public  static  void  main(String[] args){
           MyRunnable MyRunnable1 =  new  MyRunnable(1);
           Thread Thread1 =  new  Thread(MyRunnable1);
           MyRunnable MyRunnable2 =  new  MyRunnable(2);
           Thread Thread2 =  new  Thread(MyRunnable2);
           Thread1.start();
           Thread2.start();
     }
}
可能的結果:
1:0
1:1
1:2
2:0
2:1
2:2
2:3
2:4
1:3
1:4
 
場景應用:
一、車站多個窗口買票,車票總數是一定的,實現Runnable可以共享總票數。
package  com.zsz.thread;
 
class  SaleTicket   implements  Runnable{
      private  int  ret  = 5;  //剩下票數
      private  int  num ;             //一次買票張數
     
      public  SaleTicket(  int  num){
             this .  num  = num;
     }
      @Override
      public  void  run() {
             synchronized (  this ){
                  if (  num >  ret ){
                     System.  out .println(  "余票不足" );
                       return ;
                }
                  ret  =  ret  -  num ;
                System.  out .println(  "出票" + num + "張成功,剩余票數:"  + ret  );   //出票成功
           }
     }
}
public  class  MyRunnable  extends  Thread{
      public  static  void  main(String[] args){
           SaleTicket saleTicket1 =  new  SaleTicket(1);
             new  Thread(saleTicket1).start();
             new  Thread(saleTicket1).start();
             new  Thread(saleTicket1).start();
             new  Thread(saleTicket1).start();
             new  Thread(saleTicket1).start();
             new  Thread(saleTicket1).start();
             new  Thread(saleTicket1).start();
     }
}
可能的執行結果:
出票1張成功,剩余票數:4
出票1張成功,剩余票數:3
出票1張成功,剩余票數:2
出票1張成功,剩余票數:1
出票1張成功,剩余票數:0
余票不足
余票不足
注:考慮數據同步和線程安全,synchronized (this)確保同步,確保一個時刻只有一個線程占用 synchronized 程序塊, 否則會出現線程不安全的情況,。
實現Runnable接口相比繼承Thread類:
1):適合多個相同的程序代碼的線程去處理同一個資源
2):可以避免java中的單繼承的限制
3):增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立。
 
main方法其實也是一個線程。
線程其他情況:
線程休眠: Thread.sleep( 2000 );
線程中斷: new  Thread( new Runnable() ).interrupt();
線程優先級: new  Thread( new Runnable() ).setPriority(8);
 
線程的狀態及說明:
1、新建狀態(New):新創建了一個線程對象。 
2、就緒狀態(Runnable):線程對象創建后,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3、運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。 
4、阻塞狀態(Blocked):阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。阻塞的情況分三種: 
  4.1、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。 
  4.2、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。 
  4.3、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。 
5、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
 
關鍵字volatile
 
用volatile修飾的變量,線程在每次使用變量的時候,都會讀取變量修改后的最的值。volatile很容易被誤用,用來進行原子性操作。
volatile不用做原子性操作的原因是:線程在運行時會在線程內存塊中變量副本,之后,主內存中的變量與線程內的變量不聯系,當運行結束時,線程內的變量會將值同步給主內存,因而會有可能出現線程不安全。
 
 有相關問題,可以提出來一起討論。后續將會張貼一些進階的多線程、線程池內容。
 
 博客園原文地址:http://www.cnblogs.com/zhongshengzhen
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM