java線程簡單介紹

來源:互聯網
上載者:User

在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();
 }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.