黑馬程序員 JAVA基礎 多線程

                                            ------- android培訓java培訓期待與您交流! ----------

 

1:多線程
 (1)線程:線程是進行的執行單元,執行路徑。
  進程:就是正在運行的程序。一塊正在被使用的內存區域。
  如果一個應用程序的執行只有一條執行路徑,被稱爲單線程程序。
  如果一個應用程序的執行有多條執行路徑,被稱爲多線程程序。
  
  舉例:
   迅雷下載,360管理界面,班長請吃飯,去醫院體檢
 (2)JVM的啓動是多線程的嗎?
  是。因爲如果JVM啓動只啓動了main線程的話,那麼,在程序的執行過程中,
  有可能會引發內存溢出,而java很少看到這種情況,爲什麼呢,就是因爲,
  java的垃圾回收線程一直也在運行,當內存不夠的情況,會自動去掃描內存中
  是否有垃圾存在,有就立馬清除。
  這樣來說,最低有兩個線程啓動了。所以,JVM的啓動是多線程的。
 (3)自己如何模擬多線程程序
  
A:繼承Thread類
   步驟:
    a:創建一個類,繼承Thread類
    b:重寫run方法
    c:創建類對象,調用start方法

   代碼體現:
    
   
 public class ThreadDemo extends Thread
    {
     @Override
     public void run()
     {
      for(int x=0; x<100; x++)
      {
       System.out.println(getName()+"***"+x);
      }
     }
    }

    public class ThreadDemoTest
    {
     public static void main(String[] args)
     {
      ThreadDemo td1 = new ThreadDemo("劉備");
      ThreadDemo td2 = new ThreadDemo("孫權");

      td1.start();
      td2.start();
     }
    }

  B:實現Runnable接口
   步驟:
    a:創建一個類,實現Runnable接口
    b:重寫run方法
    c:創建Thread類對象,創建Runnable子類對象,把Runnable的子類
      對象作爲構造參數傳遞給Thread的構造方法
    d:調用start方法  
    
   代碼體現:
    
   
 public class RunnableDemo implements Runnable
    {
     @Override
     public void run()
     {
      for(int x=0; x<100; x++)
      {
       System.out.println(Thread.currentThread().getName()+"***"+x);
      }
     }
    }

    public class ThreadDemoTest
    {
     public static void main(String[] args)
     {
      RunnableDemo rd = new RunnableDemo();

      Thread td1 = new Thread(rd,"林青霞");
      Thread td2 = new Thread(rd,"劉意");

      td1.start();
    
  td2.start();
     }
    }
 (4)實現多線程的方式有幾種,分別怎麼實現?
 (5)啓動線程調用的是哪個方法,它做了什麼事情?
  啓動線程調用的是start()方法。
  它啓動線程,並且自動調用了run()方法。

  start()和run()的區別?
 (6)線程的生命週期及每個狀態的特點。
  新建:創建線程對象
  就緒:具有執行資格,沒有執行權
  運行:具有執行資格,有執行權
   阻塞:沒有執行資格,沒有執行權
  死亡:對象變成垃圾

內存體現:

黑馬程序員  JAVA基礎三 多線程 - 619294300 - 619294300的博客

 

  
 (7)下午通過賣票程序演示出線程安全問題。
  A:線程安全是怎麼產生的?
   線程的隨機性
   線程的延遲性
  B:如何判斷某段代碼有沒有線程安全問題呢?
   a:有沒有共享數據
   b:看是否有多條語句操作共享數據
   c:看是否有多個線程進行操作
  c:如何解決線程安全問題?
   a:同步代碼塊
    synchronized(對象)
    {
     需要被同步的代碼。
    }

    對象:可以是任意對象。
   b:同步方法
    在方法上添加synchronized關鍵字即可

    鎖對象:this

    注意:靜態方法的鎖對象 當前類的字節碼文件對象。
          類名.class
  D:同步前提
   a:兩個以上的線程操作的時候
   b:對這多個線程加同步必須使用的是同一把鎖
  E:同步弊端
   每次程序的執行都會去判斷鎖對象,消耗了資源,降低了效率。

   線程安全,效率低。
   線程不安全,效率高。

   開發中的一個難題:要麼效率,要麼安全。
 (8)賣票程序
  public class Ticket implements Runnable
  {
   //定義100張票
  
 private int tickets = 100;
  
   @Override
   public void run()
   {
    while(true)
    {
     synchronized(this){
      if(tickets>0)
      {
       try{
        Thread.sleep(10);
       }catch(InterruptedException e){
        e.printStackTrace();
       }
       System.out.println(Thread.currentThread().getName()+"正在賣出第"+(tickets--)+"張票");
      }
     }
    }
   }
  }

  public class Test
 
 {
   public static void main(String[] args)
   {
    Ticket t = new Ticket();

    Thread t1 = new Thread(t,"窗口1");
    Thread t2 = new Thread(t,"窗口2");
    Thread t3 = new Thread(t,"窗口3");
    Thread t4 = new Thread(t,"窗口4");
    
    t1.start();
    t2.start();
    t3.start();
    t4.start();
   }
  }
 (9)單例設計模式的懶漢式,請問他有沒有線程安全問題

  public class Student
  {
   private Student(){}

   private static Student s = null;

   public synchronized static Student getStudent()
   {
    //t1,t2,t3
    if(s==null) 
    {
     //t1,t2,t3
     s = new Student();

     //t1線程首先創建了一個對象
     //t2線程繼續創建了一個對象
     //t3線程又創建了一個對象
    }
    return s;
   }
  }

  A:延遲加載
  B:線程安全問題


  //開發中,用餓漢式即可。
  public class Student
  {
   private Student(){}

   private static Student s = new Student();

   public static Student getStudent()
   {
    return s;
   }
  }

線程範圍內的共享數據:在同一個線程數據共享,但在不同線程,數據不共享。

代碼體現:

private static int date = 0;//共享數據
 
public static void main(String[] args) {
          for( int i=0;i<=1;i++){
           new Thread(new Runnable(){
              @Override 

public void run() {
     date = new Random().nextInt();
     System.out.println("***"+Thread.currentThread().getName()+"***"+date);
     new A().get();
     new B().get();
    }
   }).start(); 
   
   
  }
 }
 static class A{
  public void get(){
   System.out.println("A***"+Thread.currentThread().getName()+"***"+date);
  }
 }
 static class B{
 
 public void get(){
   System.out.println("B***"+Thread.currentThread().getName()+"***"+date);
  }
 }
 
}

                               ------- android培訓java培訓期待與您交流! ----------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章