日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

黑马程序员---java基础------------------多线程

發(fā)布時間:2025/3/17 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 黑马程序员---java基础------------------多线程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  線程:就是進程中的一個獨立的控制單元。線程在控制著進程的執(zhí)行。

  線程的創(chuàng)建

    一:繼承Thread類。步驟:

      1,定義類繼承Thread。

      2,復(fù)寫Thread類中的run方法。????? 目的:將自定義代碼存儲在run方法。讓線程運行。

            class Demo extends Thread
            {
?                public void run()
?                {
??                    for(int x=0; x<60; x++)
???                        System.out.println("demo run----"+x);
?                }
            }

      3,調(diào)用線程的start方法,?????????????? 該方法兩個作用:啟動線程,調(diào)用run方法。

            

            class ThreadDemo { ?

                public static void main(String[] args) ?{ ?

                    ?//for(int x=0; x<4000; x++) ??

                    //System.out.println("Hello World!");

??                   Demo d = new Demo();//創(chuàng)建好一個線程。 ??

                    //d.start();//開啟線程并執(zhí)行該線程的run方法。 ?

                   ?d.run();//僅僅是對象調(diào)用方法。而線程創(chuàng)建了,并沒有運行。

?? ??                  for(int x=0; x<60; x++) ???

                        System.out.println("Hello World!--"+x);

                ?}

?            }

      線程的運行狀態(tài):

          

    二:創(chuàng)建線程的第二種方式:實現(xiàn)Runable接口        

        步驟:

          1,定義類實現(xiàn)Runnable接口

          2,覆蓋Runnable接口中的run方法。 ?將線程要運行的代碼存放在該run方法中。

          3,通過Thread類建立線程對象。

          4,將Runnable接口的子類對象作為實際參數(shù)傳遞給Thread類的構(gòu)造函數(shù)。

          5,調(diào)用Thread類的start方法開啟線程并調(diào)用Runnable接口子類的run方法。

class Ticket implements Runnable//extends Thread {     

      private? int tick = 100;     

      public void run() { ?       

          while(true) { ??         

              if(tick>0) ??           

                System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--); ?     

          }

      }

}

class? TicketDemo {?

    public static void main(String[] args)? {

?       Ticket t = new Ticket();

?       Thread t1 = new Thread(t);//創(chuàng)建了一個線程;??

      ? Thread t2 = new Thread(t);//創(chuàng)建了一個線程;??

      ? Thread t3 = new Thread(t);//創(chuàng)建了一個線程;??

      ? Thread t4 = new Thread(t);//創(chuàng)建了一個線程;??

       t1.start();?

      ? t2.start();?

      ? t3.start();?

      ? t4.start();

    }

}

      為什么要將Runnable接口的子類對象傳遞給Thread的構(gòu)造函數(shù)?
?        因為,自定義的run方法所屬的對象是Runnable接口的子類對象。所以要讓線程去指定指定對象的run方法。就必須明確該run方法所屬對象。

      實現(xiàn)方式和繼承方式有什么區(qū)別呢?

        實現(xiàn)方式好處:避免了單繼承的局限性。在定義線程時,建議使用實現(xiàn)方式。

        繼承Thread:線程代碼存放Thread子類run方法中。

        實現(xiàn)Runnable,線程代碼存在接口的子類的run方法。

      獲取當(dāng)前線程對象:static Thread currentThread();

      獲取線程名稱:getName();

?

class Test extends Thread {??

    Test(String name) ?{ ??//父類有這樣的構(gòu)造方法

      super(name); ?

    } ?

    public void run() ?{ ??

        for(int x=0; x<60; x++) ??{ ???

          System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x); ??

        }

    ?}

}

class ThreadTest
{
?  public static void main(String[] args)
?  {
??    Test t1 = new Test("one---");
??    Test t2 = new Test("two+++");
??    t1.start();
??    t2.start();

  }

}

    多線程的安全問題:通過分析,發(fā)現(xiàn),打印出0,-1,-2等錯票。問題的原因:當(dāng)多條語句在操作同一個線程共享數(shù)據(jù)時,一個線程對多條語句只執(zhí)行了一部分,還沒有執(zhí)

行完,另一個線程參與進來執(zhí)行。導(dǎo)致共享數(shù)據(jù)的錯誤。解決辦法:對多條操作共享數(shù)據(jù)的語句,只能讓一個線程都執(zhí)行完。在執(zhí)行過程中,其他線程不可以參與執(zhí)行。這就出來了

同步代碼塊

synchronized(對象) { ?

    需要被同步的代碼

}

    對象如同鎖。持有鎖的線程可以在同步中執(zhí)行。 沒有持有鎖的線程即使獲取cpu的執(zhí)行權(quán),也進不去,因為沒有獲取鎖。

    同步的前提:1,必須要有兩個或者兩個以上的線程;2,必須是多個線程使用同一個鎖。    

    好處:解決了多線程的安全問題。

    弊端:多個線程需要判斷鎖,較為消耗資源。

class Ticket implements Runnable {

    ?private? int tick = 1000; ?

    Object obj = new Object(); ?

    public void run() ?{ ??

        while(true) ??{ ???

          synchronized(obj) ???{ ????

            if(tick>0) ????{ ?????

                //try{Thread.sleep(10);}catch(Exception e){} ????

                ?System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--); ???

            ?} ???

          } ??

        } ?

     }

}

?

class? TicketDemo2 { ?

      public static void main(String[] args) ?{

?        ?Ticket t = new Ticket();

??        Thread t1 = new Thread(t); ??

        ? Thread t2 = new Thread(t); ??

        ? Thread t3 = new Thread(t); ??

        ??Thread t4 = new Thread(t); ??

        ? t1.start(); ?

         ?t2.start(); ??

        ? t3.start(); ??

        ? t4.start();

      }

?}

      同步函數(shù):同步代碼塊用來封裝代碼的,函數(shù)也是來封裝代碼的,我們試圖讓函數(shù)具備同步性,也可以達(dá)到相同的效果。   

class Bank { ?

    private int sum;??

    public synchronized void add(int n) ?{ ?

         ?sum = sum + n; ??

         ?try{Thread.sleep(10);

         }catch(Exception e){} ???

         System.out.println("sum="+sum);???

    ??}

}

class Cus implements Runnable {

     ?private Bank b = new Bank(); ?

    ? public void run() ?{?? ??

        for(int x=0; x<3; x++) ??{

            ???b.add(100); ??

        }

    ?}

}

class? BankDemo { ?

    public static void main(String[] args) ?{

   ??   Cus c = new Cus(); ??

      Thread t1 = new Thread(c); ??

      Thread t2 = new Thread(c); ?

    ?  t1.start(); ??

      t2.start(); ?

    }

}

    驗證同步函數(shù)的鎖對象是this:如果直接將synchronized關(guān)鍵字放到run()?函數(shù)上做成同步函數(shù),發(fā)現(xiàn)效果不行?,應(yīng)為只啟動了0號線程,分析后得知,是同步的代碼沒弄清楚,后來將同步代碼部分提取后,封裝成獨立的show()函數(shù)調(diào)用并同步synchronized,就可以了。這個時候問一個問題,它的鎖是什么呢?函數(shù)需要被對象調(diào)用,函數(shù)都有一個所屬對象的引用時this所以同步函數(shù)的鎖對象是this。為了驗證,使用兩個線程買票,一個線程在同步代碼快中,一個在同步函數(shù)中,都在執(zhí)行買票動作,如果要是同步就不會出現(xiàn)錯誤的票。

class Ticket implements Runnable { ?

    private? int tick = 100; ?

    //Object obj = new Object(); ?

    boolean flag = true; ?

    public? void run() ?{ ??

        if(flag) ??{ ???

            while(true) ???{ ????

                //synchronized(this) ????{ ?????

                    if(tick>0) ?????{ ?????

              ?          try{Thread.sleep(10);}catch(Exception e){} ??????

                         System.out.println(Thread.currentThread().getName()+"....code : "+ tick--); ?????

                    } ????

                } ??

      ?      } ??

         } ??

    ?     else ???

            while(true) ????

                show(); ?

    }

    ?public synchronized void show()//this ?

    { ??

        if(tick>0) ??{ ??

          ?try{Thread.sleep(10);}catch(Exception e){} ???

          System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--); ??

        } ?

    }

}

class? ThisLockDemo {

    ?public static void main(String[] args) ?{

??        Ticket t = new Ticket();

??        Thread t1 = new Thread(t); ??

        ? Thread t2 = new Thread(t); ??

        ? t1.start(); ??

        ? try{

            Thread.sleep(10);

         }catch(Exception e){} ?

    ?    t.flag = false; ??

        t2.start();
?    }
}

    函數(shù)被靜態(tài)修飾后,使用的鎖是:類名.class

?

class Ticket implements Runnable { ?

    private static? int tick = 100; ?

    //Object obj = new Object();

    ?boolean flag = true; ?

    public? void run() ?{ ??

      if(flag) ??{ ??

        ?  while(true) ???{ ????

              synchronized(Ticket.class) ????{ ????

                ?  if(tick>0) ?????{ ??????

                      try{Thread.sleep(10);}catch(Exception e){} ??????

                      System.out.println(Thread.currentThread().getName()+"....code : "+ tick--); ????

                ?  } ????

              } ???

           } ??

       } ??

       else ???

          while(true) ????

              show(); ?

    } ?

    public static synchronized void show() ?{ ??

          if(tick>0) ??{ ???

              try{Thread.sleep(10);}catch(Exception e){} ???

              System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--); ??

          }??

    }

}

?

class? StaticMethodDemo {

    ?public static void main(String[] args) ?{

??        Ticket t = new Ticket();

??        Thread t1 = new Thread(t); ??

        ? Thread t2 = new Thread(t); ?

         ?t1.start(); ??

        ? try{Thread.sleep(10);}catch(Exception e){} ??

        ? t.flag = false; ?

         ?t2.start();

    ?}

}

單例設(shè)計模式

懶漢式:

class Single { ?

    private static Single s = null; ?

    private Single(){}

?    public static? Single getInstance() ?{ ??

        if(s==null) ??{ ???

            synchronized(Single.class) ???{ ????

                if(s==null) ?????

                //--->A; ?????

                s = new Single(); ???

            } ??

        } ??

        return s; ?

     }

}

class SingleDemo { ?

    public static void main(String[] args) ?{ ??

        System.out.println("Hello World!"); ?

    }

}

    死鎖:

class Test implements Runnable { ?

    private boolean flag; ?

    Test(boolean flag) ?{ ??

        this.flag = flag; ?

    }

?    public void run() ?{ ??

        if(flag) ??{ ???

            while(true) ???{ ????

                synchronized(MyLock.locka) ????{ ?????

                      System.out.println(Thread.currentThread().getName()+"...if locka "); ?????

                      synchronized(MyLock.lockb) ?????{ ??????

                          System.out.println(Thread.currentThread().getName()+"..if lockb");????? ?????

                      } ????

                } ???

            } ??

        } ??

        else ??{ ???

            while(true) ???{ ????  

                synchronized(MyLock.lockb) ????{ ?????

                      System.out.println(Thread.currentThread().getName()+"..else lockb"); ?????

                      synchronized(MyLock.locka) ?????{ ??????

                          System.out.println(Thread.currentThread().getName()+".....else locka"); ?????

                } ????

            } ???

        } ??

    } ?

  }

}

class MyLock { ?

    static Object locka = new Object(); ?

    static Object lockb = new Object();

}

class? DeadLockTest { ?

    public static void main(String[] args) ?{ ??

        Thread t1 = new Thread(new Test(true)); ??

        Thread t2 = new Thread(new Test(false)); ??

        t1.start(); ??

        t2.start(); ?

    }

}

?

轉(zhuǎn)載于:https://www.cnblogs.com/zhaolibin198627/archive/2013/05/24/3097980.html

總結(jié)

以上是生活随笔為你收集整理的黑马程序员---java基础------------------多线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。