bomberlhl

          統(tǒng)計(jì)

          留言簿(1)

          閱讀排行榜

          評(píng)論排行榜

          2009年12月1日 #

          【轉(zhuǎn)】使用synchronized進(jìn)行Java線程同步

          線程同步指多個(gè)線程同時(shí)訪問某資源時(shí),采用一系列的機(jī)制以保證同時(shí)最多只能一個(gè)線程訪問該資源。
          為什么需要線程同步呢?
          我們舉一個(gè)最簡(jiǎn)單的例子來說明為什么需要線程同步。
          比如有一本書(有且只有一本),交給多個(gè)售貨員同時(shí)去賣;
          如果其中任何一個(gè)售貨員把這本書給賣了,其他售貨員就不能再賣這本書了。
          現(xiàn)實(shí)生活中,如果要保證該書不會(huì)被多個(gè)售貨員同時(shí)賣掉,必須要有一種機(jī)制來保證:
          比如,售貨員應(yīng)該拿到該書之后才能開始賣書,暫時(shí)拿不到的話就只能等該書被退回柜臺(tái)。

          售書的完整的例子可以參考 范例解說Java里的線程概念與線程同步技術(shù) 一文

          這里,每一個(gè)售貨員售書可以看作一個(gè)線程。欲售的書便是各線程需要共享的資源。
          開始售書之前,需要取得該書(資源),取不到情況下等待:資源取得
          開始售書之后,則需要取得對(duì)該書的獨(dú)享控制(不讓他人拿到該書):資源加鎖
          售完書時(shí),需要通知柜臺(tái)該書已售出;或者未售出時(shí),把書退回柜臺(tái)(通知他人可以拿到該書):資源解鎖

          synchronized控制線程同步的概念跟此完全一樣。
          Java里可以使用synchronized來同步代碼塊或者方法。
          同步代碼塊例:
          1. synchronized(欲同步的對(duì)象obj) {
          2.     需要同步的代碼塊   
          3. }  

          可以同步代碼塊。

          synchronized (obj) 表示若多個(gè)線程同時(shí)訪問時(shí),只讓其中一個(gè)線程最先取得obj對(duì)象并對(duì)其加鎖,其它線程則阻塞直到取得obj對(duì)象的線程執(zhí)行完代碼塊,此時(shí)被加鎖的obj對(duì)象得到釋放(解鎖),其它線程得到通知取得該book對(duì)象繼續(xù)執(zhí)行。
          很多情況下,可以使用synchronized (this){...}來同步代碼塊。但需要注意的是,使用this作為同步對(duì)象的話,如果同一個(gè)類中存在多個(gè)synchronized (this){...}代碼塊,其中任何一個(gè)synchronized(this)代碼塊處于被執(zhí)行狀態(tài),則其它線程對(duì)其他synchronized(this)代碼塊的訪問也會(huì)受到阻塞。
          為了說明這個(gè)問題,我們舉例說明:

          HelloSynchronized.java
          1. publicclass HelloSynchronized {   
          2. publicstaticvoid main(String[] args) {   
          3. //
          4.         HelloSynchronized helloSynchronized = new HelloSynchronized();   
          5. //創(chuàng)建2個(gè)線程t1, t2,分別調(diào)用HelloSynchronized helloSynchronized的2個(gè)方法method1,與method2
          6.         Thread t1 = new Thread(new HelloSynchronizedRunnalbe(helloSynchronized, "method1"), "t1");   
          7.         Thread t2 = new Thread(new HelloSynchronizedRunnalbe(helloSynchronized, "method2"), "t2");   
          8.         t1.start();   
          9.         t2.start();   
          10.     }   
          11. //synchronized public void method1() {    //同步方法
          12. publicvoid method1() {   
          13. synchronized (this) {    //同步塊
          14.             System.out.println(Thread.currentThread().getName()
          15.                     + " enter method1");   
          16. try {
          17.                 Thread.sleep(3000);   
          18.             } catch (InterruptedException e) {
          19. // do nothing
          20.             }   
          21.             System.out.println(Thread.currentThread().getName()
          22.                     + " exit method1");   
          23.         }   
          24.     }   
          25. //synchronized public void method2() {    //同步方法
          26. publicvoid method2() {   
          27. synchronized (this) {    //同步塊
          28.             System.out.println(Thread.currentThread().getName()
          29.                     + " enter method2");   
          30. try {
          31.                 Thread.sleep(3000);   
          32.             } catch (InterruptedException e) {
          33. // do nothing
          34.             }   
          35.             System.out.println(Thread.currentThread().getName()
          36.                     + " exit method2");   
          37.         }   
          38.     }   
          39. }   
          40. class HelloSynchronizedRunnalbe implements Runnable {   
          41. private HelloSynchronized helloSynchronized;
          42. private String methodName;   
          43. public HelloSynchronizedRunnalbe(HelloSynchronized helloSynchronized, String methodName) {
          44. this.helloSynchronized = helloSynchronized;
          45. this.methodName = methodName;   
          46.     }   
          47. publicvoid run() {   
          48. if (methodName.equals("method1")) {   
          49.             helloSynchronized.method1();   
          50.         } elseif (methodName.equals("method2")) {   
          51.             helloSynchronized.method2();   
          52.         }   
          53.     }   
          54. }  


          運(yùn)行結(jié)果為:
          t1 enter method1
          t1 exit method1
          t2 enter method2
          t2 exit method2
          等到線程t1結(jié)束后,t2才開始運(yùn)行(t2受到阻塞)

          再把synchronized (this)去掉,運(yùn)行結(jié)果為:
          t1 enter method1
          t2 enter method2
          t1 exit method1
          t2 exit method2
          線程t1,t2同時(shí)運(yùn)行

          同步方法例:
          1. synchronizedprivatevoid sellBook(Book book) {   
          2. ...   
          3. }  

          這種方法其實(shí)相當(dāng)于
          1. privatevoid sellBook(Book book) {   
          2. synchronized(this) {   
          3.         ...   
          4.     }   
          5. }  

          由于默認(rèn)采用this作為同步對(duì)象,所以當(dāng)一個(gè)類中有多個(gè)synchronized方法時(shí),同樣會(huì)存在以上問題:即如果有一個(gè)線程訪問其中某個(gè)synchronized方法時(shí),直到該方法執(zhí)行完畢,其它線程對(duì)其它synchronized方法的訪問也將受到阻塞。
          大家可以把上面的例子稍加改造,去掉代碼中的synchronized (this),改為synchronized public void method1(),synchronized public void method2()同步形式,運(yùn)行后會(huì)得到同樣結(jié)果。

          多同步代碼塊synchronized(this){...}的多線程阻塞問題(包括synchronized同步方法),在并發(fā)處理的系統(tǒng)中(比如WEB服務(wù)器)會(huì)嚴(yán)重影響性能,建議慎重使用。可以使用synchronized(obj){...}縮小同步資源對(duì)象的范圍來解決這個(gè)問題。

          posted @ 2009-12-14 19:33 異域流浪 閱讀(288) | 評(píng)論 (0)編輯 收藏

          【轉(zhuǎn)】范例解說Java里的線程概念與線程同步技術(shù)

          線程 是一段完成某個(gè)特定功能的代碼,程序中的執(zhí)行線程。Java 虛擬機(jī)允許應(yīng)用程序并發(fā)地運(yùn)行多個(gè)執(zhí)行線程。
          每個(gè)線程都有一個(gè)優(yōu)先級(jí),高優(yōu)先級(jí)線程的執(zhí)行優(yōu)先于低優(yōu)先級(jí)線程。
          進(jìn)程不同的是,由同名類生成的多個(gè)線程共享相同的內(nèi)存空間和系統(tǒng)資源。

          線程與進(jìn)程的區(qū)別:
          一個(gè)線程是一個(gè)程序內(nèi)部的順序控制流。
          1. 進(jìn)程:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文) ,進(jìn)程切換的開銷大。線程:同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線程切換的開銷小。
          2. 一個(gè)進(jìn)程中可以包含多個(gè)線程。

          本文將介紹以下線程方面的知識(shí):
          1,線程的創(chuàng)建
          2,線程的狀態(tài)
          3,線程同步
          4,線程組

          理解線程的最有效的方法是通過實(shí)例來理解。下面我們將通過 售貨員售書 為例,由淺入深地介紹線程的創(chuàng)建,通信,鎖機(jī)制等概念。

          售貨員售書
          我們假設(shè)一下售貨員售書的操作流程:
          1,我們假設(shè)有20本書,交給2個(gè)售貨員去賣。
          2,售貨員可以賣掉任何一本尚未賣出去的書。換句話說,同一本書若被其中一位售出去了,則不能被另外一位再售出了。


          清單1:
          文件名說明
          Book.java 書籍類
          SellBookRunnable.java 售書類,線程的創(chuàng)建方法之一,該類實(shí)現(xiàn)了Runnable 接口,并實(shí)現(xiàn)了 run 方法。
          SellBookThread.java 售書類,線程的創(chuàng)建方法之一,該類聲明為 Thread 的子類,并重寫 Thread 類的 run 方法。
          CallSellBook.java 調(diào)用類。該類分別介紹了2種不同線程創(chuàng)建的調(diào)用方法。

          Book.java
          1. publicclass Book {   
          2. private String name;
          3. privateboolean sold = false;   
          4. public Book(String name) {   
          5. this.name = name;
          6.     }   
          7. public String getName() {
          8. return name;
          9.     }   
          10. publicvoid setName(String name) {   
          11. this.name = name;   
          12.     }   
          13. publicboolean isSold() {   
          14. return sold;
          15.     }   
          16. publicvoid setSold(boolean sold) {   
          17. this.sold = sold;   
          18.     }   
          19. }  



          SellBookRunnable.javatil.List;
          1. publicclass SellBookRunnable implements Runnable {   
          2. private String saleMan;
          3. private List<Book> bookList;
          4. public SellBookRunnable(String saleMan, List<Book> bookList) {
          5. this.saleMan = saleMan;   
          6. this.bookList = bookList;   
          7.     }   
          8. publicvoid run() {   
          9. for (int i = 0; i < bookList.size(); i++) {
          10.             Book book = bookList.get(i);   
          11.             sellBook(book);   
          12.         }   
          13.     }   
          14. /**  
          15.      * 售貨員賣書。我們這樣描述售貨員的賣書過程。  
          16.      *   
          17.      * @param book Book  
          18.      */
          19. privatevoid sellBook(Book book) {   
          20. //從開始售書-到售書完成,使用synchronized (book)保證book不被其他售貨員售出
          21. synchronized (book) {
          22. if (book.isSold()) {   
          23. return;
          24.             } else {
          25. try {
          26. //為了讓各線程有執(zhí)行機(jī)會(huì),設(shè)置平均售書時(shí)間為0.5秒
          27.                     Thread.sleep(500);   
          28.                 } catch (Exception e) {   
          29.                 }   
          30. //設(shè)置已售標(biāo)志
          31.                 book.setSold(true);   
          32. //打印該書已售信息
          33.                 System.out.println("[" + saleMan + "]" + book.getName() + " sold out:"
          34.                         + book.isSold() + ". by "
          35.                         + Thread.currentThread().getName());
          36.             }   
          37.         }   
          38.     }   
          39. }  



          SellBookThread.java

          1. import java.util.List;
          2. publicclass SellBookThread extends Thread {   
          3. private String saleMan;
          4. private List<Book> bookList;
          5. public SellBookThread(String saleMan, List<Book> bookList) {
          6. this.saleMan = saleMan;   
          7. this.bookList = bookList;   
          8.     }   
          9. publicvoid run() {   
          10. for (int i = 0; i < bookList.size(); i++) {
          11.             Book book = bookList.get(i);   
          12.             sellBook(book);   
          13.         }   
          14.     }   
          15. /**  
          16.      * 售貨員賣書。我們這樣描述售貨員的賣書過程。  
          17.      *   
          18.      * @param book Book  
          19.      */
          20. privatevoid sellBook(Book book) {   
          21. //從開始售書-到售書完成,使用synchronized (book)保證book不被其他售貨員售出
          22. synchronized (book) {
          23. if (book.isSold()) {   
          24. return;
          25.             } else {
          26. try {
          27. //為了讓各線程有執(zhí)行機(jī)會(huì),設(shè)置平均售書時(shí)間為0.5秒
          28.                     Thread.sleep(500);   
          29.                 } catch (Exception e) {   
          30.                 }   
          31. //設(shè)置已售標(biāo)志
          32.                 book.setSold(true);   
          33. //打印該書已售信息
          34.                 System.out.println("[" + saleMan + "]" + book.getName() + " sold out:"
          35.                         + book.isSold() + ". by "
          36.                         + Thread.currentThread().getName());
          37.             }   
          38.         }   
          39.     }   
          40. }  



          CallSellBook.java

          1. import java.util.ArrayList;
          2. import java.util.List;
          3. //該類調(diào)用SellBookXxx類
          4. publicclass CallSellBook {   
          5. /**  
          6.      * 用線程模擬這個(gè)售書的過程  
          7.      */
          8. publicstaticvoid main(String[] args) {   
          9. //方法1:
          10.         callSellBookThread();   
          11. //or
          12. //方法2:
          13. //callSellBookRunnable();
          14.     }   
          15. //調(diào)用SellBookRunnable(Runnable接口實(shí)現(xiàn)類)模擬售書過程
          16. publicstaticvoid callSellBookThread() {   
          17.         List <Book>bookList = getBookListForSale();
          18. //將預(yù)售書籍清單交給售貨員SaleMan1
          19.         Thread t1 = new SellBookThread("SaleMan1", bookList);   
          20. //將預(yù)售書籍清單交給售貨員SaleMan2
          21.         Thread t2 = new SellBookThread("SaleMan2", bookList);   
          22. //售貨員SaleMan1開始售書
          23.         t1.start();   
          24. //售貨員SaleMan2開始售書
          25.         t2.start();   
          26.     }   
          27. //調(diào)用SellBookRunnable(Runnable接口實(shí)現(xiàn)類)模擬售書過程
          28. publicstaticvoid callSellBookRunnable() {   
          29.         List <Book>bookList = getBookListForSale();
          30. //將預(yù)售書籍清單交給售貨員SaleMan1
          31.         Thread t1 = new Thread(new SellBookRunnable("SaleMan1", bookList));   
          32. //將預(yù)售書籍清單交給售貨員SaleMan2
          33.         Thread t2 = new Thread(new SellBookRunnable("SaleMan2", bookList));   
          34. //售貨員SaleMan1開始售書
          35.         t1.start();   
          36. //售貨員SaleMan2開始售書
          37.         t2.start();   
          38.     }   
          39. //準(zhǔn)備預(yù)售書籍
          40. publicstatic List<Book> getBookListForSale() {
          41.         List <Book>bookList = new ArrayList();   
          42. for (int i = 0; i < 20; i++) {   
          43.             Book book = new Book("Book" + i);   
          44.             bookList.add(book);   
          45.         }   
          46. return bookList;   
          47.     }   
          48. }  


          執(zhí)行CallSellBook
          [SaleMan1]Book0 sold out:true. by Thread-0
          [SaleMan2]Book1 sold out:true. by Thread-1
          [SaleMan2]Book2 sold out:true. by Thread-1
          [SaleMan2]Book3 sold out:true. by Thread-1
          [SaleMan2]Book4 sold out:true. by Thread-1
          [SaleMan2]Book5 sold out:true. by Thread-1
          [SaleMan1]Book6 sold out:true. by Thread-0
          [SaleMan1]Book7 sold out:true. by Thread-0
          [SaleMan1]Book8 sold out:true. by Thread-0
          [SaleMan1]Book9 sold out:true. by Thread-0
          [SaleMan1]Book10 sold out:true. by Thread-0
          [SaleMan1]Book11 sold out:true. by Thread-0
          [SaleMan2]Book12 sold out:true. by Thread-1
          [SaleMan2]Book13 sold out:true. by Thread-1
          [SaleMan2]Book14 sold out:true. by Thread-1
          [SaleMan2]Book15 sold out:true. by Thread-1
          [SaleMan2]Book16 sold out:true. by Thread-1
          [SaleMan2]Book17 sold out:true. by Thread-1
          [SaleMan1]Book18 sold out:true. by Thread-0
          [SaleMan1]Book19 sold out:true. by Thread-0
          線程的創(chuàng)建
          創(chuàng)建新執(zhí)行線程有兩種方法。
          方法一種方法是將類聲明為 Thread 的子類。該子類應(yīng)重寫 Thread 類的 run 方法。事實(shí)上類Thread本身也實(shí)現(xiàn)了接口Runnable,所以我們可以同過繼承Thread類實(shí)現(xiàn)線程體。
          參考:SellBookThread.javaCallSellBook.java
          另一種方法是聲明實(shí)現(xiàn) Runnable 接口的類。該類然后實(shí)現(xiàn) run 方法。
          參考:SellBookRunnable.javaCallSellBook.java



          線程的狀態(tài)
          線程有四種狀態(tài):創(chuàng)建狀態(tài)(New),可運(yùn)行狀態(tài)(Runnable),阻塞狀態(tài)(Blocked),死亡狀態(tài)(Dead)。

          創(chuàng)建狀態(tài)(New):
          當(dāng)執(zhí)行完
          Thread t1 = new SellBookThread("SaleMan1", bookList);
          語句之后,則t1處于創(chuàng)建狀態(tài)(New)。此時(shí)t1并未真正運(yùn)行。

          可運(yùn)行狀態(tài)(Runnable):
          當(dāng)Thread t1被創(chuàng)建,并執(zhí)行完
          t1.start();
          語句之后,t1就處于可運(yùn)行狀態(tài)(Runnable)。此時(shí),系統(tǒng)為線程t1分配其所需的系統(tǒng)資源。并對(duì)t1加以調(diào)用(或者根據(jù)任務(wù)調(diào)度情況準(zhǔn)備調(diào)用)。

          阻塞狀態(tài)(Blocked):
          由于以下原因:
          1) 調(diào)用了sleep()方法;
          2) 調(diào)用了suspend()方法(該方法已不推薦使用);
          3) 為等待條件鎖,調(diào)用wait()方法等;
          4) 輸入輸出,或消息發(fā)生阻塞;

          使得線程處于阻塞狀態(tài)(Blocked)。處于該狀態(tài)的線程即使處理器空閑,也不會(huì)得到執(zhí)行。

          死亡狀態(tài)(Dead):
          死亡狀態(tài)(Dead)可以為自然死亡(線程運(yùn)行完畢),或者調(diào)用了stop()方法(該方法已不推薦使用)。


          線程的優(yōu)先級(jí):
          可以通過Thread類的    
          void setPriority(int newPriority)
          方法為線程設(shè)置優(yōu)先級(jí)。但是不能保證高優(yōu)先級(jí)的線程就會(huì)被先運(yùn)行。

          線程組:
          可以通過
          ThreadGroup group = new ThreadGroup(groupName);
          Thread t1 = new Thread(ThreadGroup g, Runnable r1);
          Thread t1 = new Thread(ThreadGroup g, Runnable r2);
          等方法把多個(gè)線程加到一個(gè)線程組里去,這樣可以通過ThreadGroup對(duì)這些線程進(jìn)行某些統(tǒng)一操作,
          例如:group.interrupt();中斷該組所有線程。


          線程unchecked異常處理器:
          可以通過:
          public void static Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)
          方法為所有線程指定一個(gè)unchecked異常處理器,該處理器必須實(shí)現(xiàn)UncaughtExceptionHandler接口。


          線程同步:
          線程同步指多個(gè)線程同時(shí)訪問某資源時(shí),采用一系列的機(jī)制以保證同時(shí)最多只能一個(gè)線程訪問該資源。
          線程同步是多線程中必須考慮和解決的問題,因?yàn)楹芸赡馨l(fā)生多個(gè)線程同時(shí)訪問(主要是寫操作)同一資源,如果不進(jìn)行線程同步,很可能會(huì)引起數(shù)據(jù)混亂,造成線程死鎖等問題。

          使用synchronized同步線程。
          在J2SE5.0之前,只能使用synchronized來同步線程。可以使用synchronized來同步代碼塊或者方法。
          同步代碼塊例:
          synchronized(欲同步的對(duì)象obj) {需要同步的代碼塊}可以同步代碼塊。

          參考:SellBookThread.java
          1. privatevoid sellBook(Book book) {   
          2. synchronized (book) {
          3.             ...   
          4.         }   
          5.     }  

          該例synchronized (book) 表示若多個(gè)線程同時(shí)訪問時(shí),只讓其中一個(gè)線程最先取得book對(duì)象,其它線程則阻塞直到代碼塊執(zhí)行完畢book對(duì)象被釋放后,其它線程才能取得該book對(duì)象繼續(xù)執(zhí)行。
          很多情況下,可以使用synchronized (this){...}來同步代碼塊。但需要注意的是,使用this作為同步對(duì)象的話,如果同一個(gè)類中存在多個(gè)synchronized (this){...}代碼塊,其中任何一個(gè)synchronized(this)代碼塊處于被執(zhí)行狀態(tài),則其它線程對(duì)其他synchronized(this)代碼塊的訪問也會(huì)受到阻塞。

          同步方法例:
          1. synchronizedprivatevoid sellBook(Book book) {   
          2. ...   
          3. }  

          這種方法其實(shí)相當(dāng)于
          1. privatevoid sellBook(Book book) {   
          2. synchronized(this) {   
          3.         ...   
          4.     }   
          5. }  

          由于默認(rèn)采用this作為同步對(duì)象,所以當(dāng)一個(gè)類中有多個(gè)synchronized方法時(shí),同樣會(huì)存在以上問題:即如果有一個(gè)線程訪問其中某個(gè)synchronized方法時(shí),直到該方法執(zhí)行完畢,其它線程對(duì)其它synchronized方法的訪問也將受到阻塞。
          有關(guān)synchronized詳細(xì)說明我們將在其它文章中加以說明。


          使用java.util.concurrent.locks.ReentrantLock和java.util.concurrent.locks.ReentrantReadWriteLock類同步線程。
          J2SE5.0加入了ReentrantLock和ReentrantReadWriteLock可以對(duì)線程進(jìn)行同步,這里舉一個(gè)最簡(jiǎn)單的例子對(duì)其加以說明:
          1. class X {
          2. privatefinal ReentrantLock lock = new ReentrantLock();   
          3. // ...
          4. publicvoid m() {    
          5.      lock.lock();  // block until condition holds
          6. try {
          7. // ... method body
          8.      } finally {
          9.        lock.unlock()   
          10.      }   
          11.    }   
          12.  }   



          其它J2SE5.0新導(dǎo)入的有關(guān)線程的相關(guān)接口/類:
          java.util.concurrent.Future
          Future接口可以保持/取得異步執(zhí)行的結(jié)果值

          java.util.concurrent.Callable
          類似于Runnable接口。但Runnable不能返回值,也不能拋出checked異常

          java.util.concurrent.ExecutorService
          該接口繼承了Executor接口。可以通過submit方法把Runnable,Callable對(duì)象轉(zhuǎn)換為Future 形式。

          java.util.concurrent.FutureTask
          該類實(shí)現(xiàn)了Runnable和Future接口。提供異步執(zhí)行的取消以及異步執(zhí)行結(jié)果的取得等功能。

          java.util.concurrent.Executor
          執(zhí)行指定的Runnable對(duì)象

          java.util.concurrent.Executors
          工具類。提供靜態(tài)方法可以創(chuàng)建Executor,ExecutorService,Callable等對(duì)象。可以通過newCachedThreadPool()等方法簡(jiǎn)單創(chuàng)建線程池。


          posted @ 2009-12-14 19:29 異域流浪 閱讀(253) | 評(píng)論 (0)編輯 收藏

          【轉(zhuǎn)】JAVA 基本數(shù)據(jù)類型 取值范圍

          先看一段代碼
          public class Hello{
              public static void main(String[] args){
                  int i  = 5 ,  j = 2;
                  System.out.println(i+j);
                  System.out.println(i-j);
                  System.out.println(i*j);
                  System.out.println(i/j);
              }
          }

          編譯運(yùn)行完上面的代碼后會(huì)得到各條指令運(yùn)行的結(jié)果:7,3,10,2
          這就是JAVA里面的加減乘除運(yùn)算,為什么5除以2不等于2.5而等于2呢?這是因?yàn)檫@里做的是整數(shù)的四則運(yùn)算,5除以2的結(jié)果是2,而余數(shù)為1,我們可以在上面的代碼上加上一條指令
          System.out.println(i%j);
          運(yùn)行這個(gè)結(jié)果就會(huì)得到余數(shù) 1,這個(gè) “%”執(zhí)行的求余,或者叫取模。
          想要得到5/2=2.5這個(gè)結(jié)果,我們需要改變對(duì)i和j的定義
          把 int i = 5 ,  j=2;  改寫成double i =5 , j = 2;
          再編譯運(yùn)行一次,會(huì)得到如下的結(jié)果: 7.0 , 3.0 , 10.0 , 2.5.
          可以看到結(jié)果都發(fā)生了變化,變成了帶小數(shù)點(diǎn)的,我們稱之為浮點(diǎn)型常量。
          跟前面的例子一樣,我們也使用了這樣的定義方法
          int i = 5,j = 2;
          Scanner s = new Scanner(System.in);
          前面說過,我們?cè)谶@里是定義了一個(gè)Scanner類型的引用變量,它指向一個(gè)Scanner對(duì)象,但是這里跟以前有點(diǎn)不一樣(大概是java中僅有的幾處不一樣的地方了),我們定義了一個(gè)int型的變量i,然后把它的值賦成5(不是指向5),以后用到它的地方就相當(dāng)于在用5做計(jì)算。
          int是我們常用到八種基本數(shù)據(jù)類型之一,它表示整數(shù)型。
          在JAVA中一共有八種基本數(shù)據(jù)類型,他們分別是
          byte、short、int、long、float、double、char、boolean
          整型
          其中byte、short、int、long都是表示整數(shù)的,只不過他們的取值范圍不一樣
          byte的取值范圍為-128~127,占用1個(gè)字節(jié)(-2的7次方到2的7次方-1)
          short的取值范圍為-32768~32767,占用2個(gè)字節(jié)(-2的15次方到2的15次方-1)
          int的取值范圍為(-2147483648~2147483647),占用4個(gè)字節(jié)(-2的31次方到2的31次方-1)
          long的取值范圍為(-9223372036854774808~9223372036854774807),占用8個(gè)字節(jié)(-2的63次方到2的63次方-1)
          可以看到byte和short的取值范圍比較小,而long的取值范圍太大,占用的空間多,基本上int可以滿足我們的日常的計(jì)算了,而且int也是使用的最多的整型類型了。
          在通常情況下,如果JAVA中出現(xiàn)了一個(gè)整數(shù)數(shù)字比如35,那么這個(gè)數(shù)字就是int型的,如果我們希望它是byte型的,可以在數(shù)據(jù)后加上大寫的B:35B,表示它是byte型的,同樣的35S表示short型,35L表示long型的,表示int我們可以什么都不用加,但是如果要表示long型的,就一定要在數(shù)據(jù)后面加“L”。

          浮點(diǎn)型
          float和double是表示浮點(diǎn)型的數(shù)據(jù)類型,他們之間的區(qū)別在于他們的精確度不同
          float 3.402823e+38 ~ 1.401298e-45(e+38表示是乘以10的38次方,同樣,e-45表示乘以10的負(fù)45次方)占用4個(gè)字節(jié)
          double 1.797693e+308~ 4.9000000e-324 占用8個(gè)字節(jié)
          double型比float型存儲(chǔ)范圍更大,精度更高,所以通常的浮點(diǎn)型的數(shù)據(jù)在不聲明的情況下都是double型的,如果要表示一個(gè)數(shù)據(jù)是float型的,可以在數(shù)據(jù)后面加上“F”。
          浮點(diǎn)型的數(shù)據(jù)是不能完全精確的,所以有的時(shí)候在計(jì)算的時(shí)候可能會(huì)在小數(shù)點(diǎn)最后幾位出現(xiàn)浮動(dòng),這是正常的。

          boolean型(布爾型)
          這個(gè)類型只有兩個(gè)值,true和false(真和非真)
          boolean t = true;
          boolean f = false;
          char型(文本型)
          用于存放字符的數(shù)據(jù)類型,占用2個(gè)字節(jié),采用unicode編碼,它的前128字節(jié)編碼與ASCII兼容
          字符的存儲(chǔ)范圍在\u0000~\uFFFF,在定義字符型的數(shù)據(jù)時(shí)候要注意加' ',比如 '1'表示字符'1'而不是數(shù)值1,
          char c = ' 1 ';
          我們?cè)囍敵鯿看看,System.out.println(c);結(jié)果就是1,而如果我們這樣輸出呢System.out.println(c+0);
          結(jié)果卻變成了49。
          如果我們這樣定義c看看
          char c = ' \u0031 ';輸出的結(jié)果仍然是1,這是因?yàn)樽址?1'對(duì)應(yīng)著unicode編碼就是\u0031
          char c1 = 'h',c2 = 'e',c3='l',c4='l',c5 = 'o';
          System.out.print(c1);System.out.print(c2);System.out.print(c3);System.out.print(c4);Sytem.out.print(c5);

          String
          在前面我們看到過這樣的定義:
          String s = "hello";
          System.out.println(s);跟上面的5條語句組合起來的效果是一樣的,那么String是個(gè)什么呢?String是字符串,它不是基本數(shù)據(jù)類型,它是一個(gè)類,但是它又是一個(gè)有一點(diǎn)點(diǎn)特殊的類,它有很多性質(zhì)和基本數(shù)據(jù)類型很像,以后我們會(huì)慢慢看到這些。

          posted @ 2009-12-01 18:03 異域流浪 閱讀(234) | 評(píng)論 (0)編輯 收藏

          主站蜘蛛池模板: 深泽县| 台江县| 望城县| 黎平县| 包头市| 施甸县| 大洼县| 易门县| 大安市| 洪江市| 阜城县| 潜江市| 台北市| 邮箱| 磐石市| 本溪市| 盖州市| 中宁县| 嘉义县| 曲水县| 民乐县| 武强县| 吉木萨尔县| 淮安市| 清河县| 通渭县| 万载县| 泽州县| 合阳县| 大邑县| 宁海县| 托克逊县| 陆丰市| 鄂托克旗| 怀化市| 剑阁县| 时尚| 乌拉特前旗| 加查县| 观塘区| 青阳县|