<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Picses' sky

    Picses' sky
    posts - 43, comments - 29, trackbacks - 0, articles - 24

    java線程簡單介紹[zz]

    Posted on 2007-07-18 10:55 Matthew Chen 閱讀(678) 評論(2)  編輯  收藏 所屬分類: Java MultiThread

    在java中,一個線程用一個Thread對象表示
    一般每一個java程序都有一個main方法(applet沒有),它是主線程的入口點
    而用Thread表示的線程,入口點自然不是main了,而是run方法
    定義一個線程,主要就是寫它的run方法
    寫run有兩種方法,一種是繼承Thread類,然后重寫它的run
    另一種是實現Runnable接口,然后重寫它的run,如下所示:
    ============================
    //用外部類實現多線程
    class  ThreadTest2
    {
     public static void main(String[] args)
     {
      new ThreadTest2();
     }
     ThreadTest2(){
      for(int i=1; i<=5; i++){
       System.out.println("creating thread "+i);
       outterThread th = new outterThread(i);//創建新線程
       th.start();//啟動剛創建的線程
      }
     }
    }

    class outterThread extends Thread//通過繼承Thread類來實現多線程;外部類
    {
     int count;
     outterThread(int i){
      count = i;
     }
     public void run() {
      while(true){
       System.out.println("thread "+count+" is running");
       try{
        sleep(1000*count);
       }
       catch(InterruptedException e){}
      }
     }
    }
    =====================================
    class ThreadTest3 implements Runnable //通過實現Runnable接口來實現多線程
    {
     int count;
     public static void main(String[] args)
     {
      for(int i=1; i<=5; i++)
       //調用了Thread類的構造函數Thread(Runnable target)
       new Thread(new ThreadTest3(i)).start();
     }
     ThreadTest3(int i){
      System.out.println("creating thread "+i);
      count = i;
     }
     public void run(){
      while(true){
       System.out.println("thread "+count+" is running");
       try{
        Thread.sleep(1000*count);//讓線程睡眠一段時間
       }
       catch(InterruptedException e){}
      }
     }
    }
    可以看到,不論如何重寫run,都要生成Thread對象.不同的是,第二種方法要在Thread的構造函數里傳入Runnable的實現類作為參數
    上面的例子還用到了start()和sleep()
    前者用作啟動線程,調用它之后,run方法就開始執行;后者使線程暫停參數指定的時間,單位是毫秒.這個sleep會拋出異常,所以要有try,catch塊
    ===========================
    在上面的例子中,在for循環中創建的線程和主線程是并列的,一個線程的結束不會影響另一個線程
    在上面的例子中,執行完for循環,主線程就結束了,而其他線程還在運行著
    用setDaemon()可以使一個線程作為后臺線程執行,也就是說,當其他非Daemon線程結束時,不論run執行完沒有,后臺線程也將退出
    反過來,你也可以使主線程等待其他線程結束后再退出.注意這里是主線程等待其他線程結束,而上面講的daemon線程是在所有非daemon(主線程和其他非daemon)退出后再退出.要實現這一目的,可使用join().它可帶可不帶參數,帶參數的話, 參數表示等待時間,如果過了這指定的時間不管join了的線程退出與否,主線程都會結束(如果main方法已經執行完了)
    下面是例子
    =======================
    class DaemonAndJoin
    {
     public static void main(String[] args)
     {
      Thread th = new Thread( new Runnable(){ 
       int count = 2;
       public void run(){
        while(count>0){
         for(int i=0; i<5; i++){
          try{
           Thread.sleep(500);
           System.out.println("in thread 1 ");
          }catch(InterruptedException e){
           e.printStackTrace();
          }
         }
         count--;
         System.out.println("one for is done");
        }
       }
      });
      Thread th2 = new Thread(new Runnable(){
       public void run(){
        while(true){
         try{
          Thread.sleep(1000);
          System.out.println("in thread 2");
         }catch(InterruptedException e){
          e.printStackTrace();
         }
        }
       }
      });
      System.out.println("main thread begins");  
      th.start(); 
      th2.setDaemon(true);//設置后臺線程
      th2.start();
      try{
       th.join();//join
      }catch(InterruptedException e){
       e.printStackTrace();
      }
      System.out.println("main thread quits");
     }
    }
    ==============
    上面例子,如果沒有th這個線程,th2和主線程都會很快結束
    如果有th,但是沒有join,主線程會很快結束,但是th2因為還有一個非daemon未結束,所以不會很快結束,而一直等到th結束才結束
    如果沒有setDaemon,則th不影響th2
    ==================
    線程的同步
    當多個線程同時對一個對象進行操作,就有可能發生問題,這時就要用線程同步來解決
    考慮下面的例子
    class SychronizedTest
    {
     public static void main(String[] args)
     {
      final Student stu = new Student();
      Thread setNameAndNumth1 = new Thread( new Runnable(){
       public void run(){
        while(true){
         synchronized(stu){
          stu.setNameAndNum("john","jj");
         }
        }
       }
      });
      Thread setNameAndNumth2 = new Thread( new Runnable(){
       public void run(){
        while(true){
         //synchronized(stu){
          stu.setNameAndNum("kate","kk");
         //}
        }
       }
      });
      setNameAndNumth1.start();
      setNameAndNumth2.start();
      System.out.println("test started:");
     }
    }
    class Student{
     private String name;
     private String id;
     private int count = 0;
     public /*synchronized*/ void setNameAndNum(String name,String id){
    //  synchronized(this){
       this.name = name;
       this.id = id;
       count++;
       if(!check())
        System.out.println( count + " unmatched name and id: "+name+" "+id);
    //  }
     }
     private boolean check(){
      return name.charAt(0) == id.charAt(0);
     }
    }
    在這個例子中,Student類有兩個屬性.
    有兩個線程,它們修改同一個Student類的實例,然后檢查修改后的這個實例的兩個屬性符不符合要求(判斷兩個屬性的第一個字符是否一樣)
    如果不符合要求,則在控制臺輸出語句,否則不輸出
    例子中有三部分注釋,每一部分說明了一種同步方式
    最上面方式使Student類的方法都按同步的方式執行
    第二種通過synchronized關鍵字,使單一一個方法,而不是全部方法按同步的方式執行
    第三種只是一個方法里的某一部分按同步的方法執行(雖然在這個例子里,方法的整個方法體都被括起來了)
    ====================================
    最后附上經典的生者消費者程序
    class WaitNotifyTest
    {
     public static void main(String[] args)
     {
      Clerk clerk = new Clerk();
      Producer producer = new Producer(clerk);
      Consumer consumer = new Consumer(clerk);
      Thread producerThread = new Thread(producer);
      Thread consumerThread = new Thread(consumer);
      producerThread.start();
      consumerThread.start();
     }
    }
    class Producer implements Runnable{
     Clerk clerk;
     Producer(Clerk clerk){
      this.clerk = clerk;
     }
     public void run(){
      System.out.println("producer starts producing product " );
      for(int i=0; i<10; i++){
       try{
        Thread.sleep( (int)(Math.random()*3000) );
       }catch(InterruptedException e){
        e.printStackTrace();
       }
       clerk.setProduct(i);
    //   System.out.println("producer is producing product " + i);
       
      }
     }
    }
    class Consumer implements Runnable{
     Clerk clerk;
     Consumer(Clerk clerk){
      this.clerk = clerk;
     }
     public void run(){
      System.out.println("consumer starts consuming product " );
      for(int i=0; i<10; i++){
       try{
        Thread.sleep( (int)(Math.random()*3000) );
       }catch(InterruptedException e){
        e.printStackTrace();
       }
       clerk.getProduct();
    //   System.out.println("consumer is consuming product "+ i);
       
      }
     }
    }
    class Clerk{
     int product = -1;
     public synchronized void setProduct(int product){
      if( this.product != -1  ){
       try{  
         wait();
        }catch(InterruptedException e){
         e.printStackTrace();
        }
      }
      this.product = product;
      System.out.println("producer is producing product " + product);
      notify();
     }
     public synchronized void getProduct(){
      if( product == -1 ){
       try{
        wait();
       }catch(InterruptedException e){
        e.printStackTrace();
       }
      }
      System.out.println("consumer is consuming product "+ product);
      this.product = -1;
      notify();
     }

    Feedback

    # re: java線程簡單介紹[zz]  回復  更多評論   

    2009-04-09 20:56 by huxianbao
    太有用了,呵呵

    # re: java線程簡單介紹[zz]  回復  更多評論   

    2009-04-09 22:56 by huxianbao
    最后一個生產者-消費者程序真的是太經典了
    呵呵
    主站蜘蛛池模板: 亚洲av无码片在线观看| 亚洲αv在线精品糸列| 亚洲av专区无码观看精品天堂| 国产好大好硬好爽免费不卡| 亚洲天堂一区二区| 57pao国产成视频免费播放 | 免费黄色网址网站| 亚洲va在线va天堂va手机| 精品久久久久成人码免费动漫| 亚洲人成伊人成综合网久久| 成年人视频在线观看免费| 亚洲人成网站18禁止| 国产精品麻豆免费版| 亚洲精品视频免费| 亚洲国产综合专区在线电影| 2021在线观看视频精品免费| 2020国产精品亚洲综合网| 国产精品99久久免费| 大妹子影视剧在线观看全集免费| 亚洲av无码乱码国产精品fc2| 久久久免费的精品| 国产精品亚洲四区在线观看 | 国产一区二区三区免费| 337p日本欧洲亚洲大胆色噜噜| 国产大片线上免费观看| 国产成人综合久久精品亚洲| 中文亚洲AV片不卡在线观看| 精品国产免费人成电影在线观看 | 免费人成网站永久| 亚洲AV无码一区二区乱孑伦AS| 亚洲成年人免费网站| 美女露隐私全部免费直播| 精品亚洲永久免费精品| 免费可以在线看A∨网站| 日本黄页网址在线看免费不卡| 亚洲av鲁丝一区二区三区| 成人在线视频免费| 叮咚影视在线观看免费完整版| 亚洲AV无码无限在线观看不卡| 丁香五月亚洲综合深深爱| av免费不卡国产观看|