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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【学习笔记】java基础核心总结

發(fā)布時(shí)間:2024/9/30 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【学习笔记】java基础核心总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

記錄:windows下查詢端口占用
netstat -ano
taskkill -pid 3648 -F
netstat -ano | findstr 8082

  • 基礎(chǔ)部分
    • 1.JDK的主要內(nèi)容如下:
    • 2.環(huán)境變量修改:
    • 3.Java程序的開發(fā)步驟
    • 4.文件命名
    • 5.字節(jié)碼文件(.class文件)
    • 6.· 標(biāo)識(shí)符
    • 7. Java 的50個(gè)關(guān)鍵字和類型轉(zhuǎn)化
    • 9.數(shù)組屬引用型變量
    • 10.對(duì)象和對(duì)象的引用
    • 11.反射
    • 12.自定義注解
    • 13.異常處理
    • 14.關(guān)于集合
      • 斷言的使用
    • 日志
    • 泛型的使用
    • 計(jì)算8+88+888+8888+…的前12項(xiàng)和
  • 進(jìn)階
    • jvm內(nèi)存管理
    • Thread與虛擬機(jī)棧


基礎(chǔ)部分

1.JDK的主要內(nèi)容如下:

開發(fā)工具 Java運(yùn)行環(huán)境 附加庫 C頭文件 源代碼
如果一個(gè)平臺(tái)只想運(yùn)行Java程序, 可以只安裝JRE 。
JRE
JRE 是個(gè)運(yùn)?環(huán)境,JDK 是個(gè)開發(fā)環(huán)境。因此寫 Java 程序的時(shí)候需要 JDK,?運(yùn)? Java 程序的時(shí)候就需要JRE。? JDK ??已經(jīng)包含了JRE,因此只要安裝了JDK,就可以編輯 Java 程序,也可以正常運(yùn)? Java 程序。但由于 JDK 包含了許多與運(yùn)??關(guān)的內(nèi)容,占?的空間較?,因此運(yùn)?普通的 Java
程序?須安裝 JDK,?只需要安裝 JRE 即可。

2.環(huán)境變量修改:

在彈出的 “編輯系統(tǒng)變量 ”對(duì)話框中為Path添加的新值是%JAVA_HOME%\bin,

3.Java程序的開發(fā)步驟

編寫源文件 編譯源文件
使用Java編譯器(javac.exe)編譯源文件, 得到字節(jié)碼文件。
運(yùn)行程序
使用Java SE平臺(tái)中的Java解釋器(java.exe)來解釋執(zhí)行字節(jié)碼文件

4.文件命名

如果源文件中有多個(gè)類,那么只能有一個(gè)類是public類;如果有—個(gè)類是public類那么源文件的名字必須與這個(gè)類的名字完全相同, 擴(kuò)展名是java;如果源文件沒有public類那么原文件名只要和某個(gè)類相同,拓展是.java就可以了

5.字節(jié)碼文件(.class文件)

如果源文件中包含多個(gè)類 , 編譯源文件將生成多個(gè)擴(kuò)展名為class 的文件 , 每個(gè)擴(kuò)展名是class的文件中只存放一個(gè)類的字節(jié)碼 , 其文件名與該類的名字相同。 這些字節(jié)碼文件被存 放在與源文件相同的目錄中。
一個(gè)Java應(yīng)用程序必須有一個(gè)類含有public static void main (String args[])方法是應(yīng)用程序的主類
使用Java解釋器(java.exe)來解釋執(zhí)行其字節(jié)碼文件。Java應(yīng)用程序總是從主類的main方法開始執(zhí)行。 因此, 需進(jìn)入主類字節(jié)碼所在目錄 , C:\chapterl> java Hello
當(dāng)使用Java解釋器運(yùn)行應(yīng)用程序時(shí) , Java虛擬機(jī)首先將程序需要的字節(jié)碼文件加載到內(nèi)存 , 然后解釋執(zhí)行字節(jié)碼文件。 當(dāng)運(yùn)行上述Java 應(yīng)用程序時(shí), 虛擬機(jī)將 Hello.class和Student. class加載到內(nèi)存。 當(dāng)虛擬機(jī)將Hello.class加載到內(nèi)存時(shí), 就為主類中的main方法分配了入口地址, 以便Java解釋器調(diào)用main方法開始運(yùn)行程序。需要特別注意的是, 在運(yùn)行程序時(shí), 不可以帶有擴(kuò)展名

6.· 標(biāo)識(shí)符

由字母、下畫線、美元符號(hào)和數(shù)字組成, 長度不受限制。

· 標(biāo)識(shí)符的第一個(gè)字符不能是數(shù)字字符。
· 標(biāo)識(shí)符不能是關(guān)鍵字(關(guān)鍵字見下面的2.1.3節(jié))。
· 標(biāo)識(shí)符不能是true、false和null(盡管true、false和null 不是 Java關(guān)鍵字)。例如, 以下都是標(biāo)識(shí)符:HappyNewYear_ava、 TigerYear_2010、 $98apple 、 hello、 Hello

7. Java 的50個(gè)關(guān)鍵字和類型轉(zhuǎn)化

abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while
對(duì)千byte型變量, 分配l個(gè)字節(jié)內(nèi)存 , 占8位 , 因此byte型變量的取值范圍是-27r–…,27-1 。對(duì)于short型變量 , 分配2個(gè)字節(jié)內(nèi)存 , 占16位,對(duì)于long型變量, 分配8個(gè)字節(jié)內(nèi)存, 占64位, 因此long型變量的取值范圍是-263~ 263_1。
注:Java沒有無符號(hào)的byte,short,int和long, 這一點(diǎn)和C語言有很大的不同 。 因此, unsigned int m,是錯(cuò)誤的變量聲明 。
對(duì)千char型變量 , 分配2個(gè)字節(jié)內(nèi)存 , 占16位, 最高位不是符號(hào)位, 沒有負(fù)數(shù)的char。 char型變量的取值范圍是0- 65 535。 對(duì)于char x =‘a(chǎn)’;內(nèi)存x中存儲(chǔ)的是97 ,97 是字符a在Unicode表中的排序位置。 因此, 允許將上面的變量聲明寫成
char x = 97;
float型float x = 22.76f,tom = 1234.987f,weight = le-12F; 需要特別注意的是常量后面必須要有后綴 f或F,對(duì)于double常量, 后面可以有后綴d或D, 但允許省略該后綴。

byte取值范圍: -128至127
short取值范圍-32768至32767
int取值范圍:-2147483648至2147483647

將這些類型按精度從低到高排列:
byte short char int long float double
當(dāng)把級(jí)別低的變量的值賦給級(jí)別高的變量時(shí), 系統(tǒng)自動(dòng)完成數(shù)據(jù)類型的轉(zhuǎn)換。例如:
float x = 100;
如果輸出x的值,結(jié)果將是100.0。
例如:
int X = 50;
floaty;
y = x;
如果輸出y的值,結(jié)果將是50.0。
當(dāng)把級(jí)別高的變量的值賦給級(jí)別低的變量時(shí),必須使用類型轉(zhuǎn)換運(yùn)算,格式如下。
int x = (int)34.89;
long y = (long)56.98F;
int z = (int)1999L;

8.%d: 輸出int類型數(shù)據(jù)。
%c: 輸出 char 型數(shù)據(jù)。
%f: 輸出浮點(diǎn)型數(shù)據(jù), 小數(shù)部分最多保留6位。
%s: 輸出字符串?dāng)?shù)據(jù)。
輸出數(shù)據(jù)時(shí)也可以控制數(shù)據(jù)在命令行的位置, 例如 , %md: 輸出的int型數(shù)據(jù)占m列。
?m.nf: 輸出的浮點(diǎn)型數(shù)據(jù)占m列, 小數(shù)點(diǎn)保留n位。
Systern.out.printf("%d,%f",12,23.78);
與C/C++不同 , Java 不允許在聲明數(shù)組中的方括號(hào)內(nèi)指定數(shù)組元素的個(gè)數(shù)
注:和C語言不同的是, Java 允許使用int型變量的值指定數(shù)組的元素的個(gè)數(shù), 例如, int size= 30;
double number[] = new double[size]
;
對(duì)二維數(shù)組 “ 數(shù)組名length"的值是它含有的一維數(shù)組的個(gè)數(shù)
int b[] [] = new int[3] [6];
b.length值是3

創(chuàng)建數(shù)組后, 系統(tǒng)會(huì)給數(shù)組的每個(gè)元素一個(gè)默認(rèn)的值, 如float型是0.0。 在聲明數(shù)組的同時(shí)也可以給數(shù)組的元素一個(gè)初始值, 如:
float boy[]= { 21.3f,23.89f,2.0f,23f,778.98f};
**

9.數(shù)組屬引用型變量

**兩個(gè)相同類型的數(shù)組如果具有相同的引用, 它們就有完全相同的元素。 例如:


需要注意的是, 對(duì)于char型數(shù)組a, System.out.println(a)不會(huì)輸出數(shù)組a的引用而是輸出 數(shù)組a的全部元素的值

10.對(duì)象和對(duì)象的引用

對(duì)象的創(chuàng)建
在 Java 中,萬事萬物都是對(duì)象。這句話相信你?定不陌?,盡管?切都看作是對(duì)象,但是你操縱的卻是?個(gè)對(duì)象的 引?(reference) 。在這?有?個(gè)很形象的?喻:你可以把?鑰匙和?看作是?組對(duì)象引?和對(duì)象的組合。當(dāng)你想要開?的時(shí)候,你?先需要拿出?鑰匙點(diǎn)擊開鎖的選項(xiàng),停?時(shí),你需要點(diǎn)
擊加鎖來鎖?。?鑰匙相當(dāng)于就是引?,?就是對(duì)象,由?鑰匙來驅(qū)動(dòng)?的加鎖和開鎖。并且,即使沒有?的存在,?鑰匙也是?個(gè)獨(dú)?存在的實(shí)體,也就是說,你有?個(gè)對(duì)象引?,但你不?定需要?個(gè)對(duì)象與之關(guān)聯(lián),也就是

Car carKey;
這?創(chuàng)建的只是引?,?并?對(duì)象,但是如果你想要使?這個(gè)引?時(shí),會(huì)返回?個(gè)異常,告訴你需要?個(gè)對(duì)象來和這個(gè)引?進(jìn)?關(guān)聯(lián)。?種安全的做法是,在創(chuàng)建對(duì)象引?時(shí)同時(shí)把?個(gè)對(duì)象賦給它。
Car carKey = new Car();
在 Java 中,?旦創(chuàng)建了?個(gè)引?,就希望它能與?個(gè)新的對(duì)象進(jìn)?關(guān)聯(lián),通常使? new 操作符來實(shí)現(xiàn)這??的。new 的意思是,給我?個(gè)新對(duì)象,如果你不想相親,?? new ?個(gè)對(duì)象就好了。祝你下輩?幸福。

11.反射



12.自定義注解


注意string name()這個(gè)是表示有一個(gè)name參數(shù),而不是一個(gè)方法名。
@TARGET用于表示這個(gè)注解可以用在類上或者方法上

用@interface表示自己定義的注解

13.異常處理

Error體系 :
Error類體系描述了Java運(yùn)行系統(tǒng)中的內(nèi)部錯(cuò)誤以及資源耗盡的情形。應(yīng)用程序不應(yīng)該拋出這種類型的對(duì)象(一般是由虛擬機(jī)拋出)。如果出現(xiàn)這種錯(cuò)誤,除了盡力使程序安全退出外,在其他方面是無能為力的。所以,在進(jìn)行程序設(shè)計(jì)時(shí),應(yīng)該更關(guān)注Exception體系。

Exception體系包括RuntimeException體系和其他非RuntimeException的體系(程序本身沒有問題,但由于像IOException這類問題導(dǎo)致的異常屬于其他異常) :
① RuntimeException:RuntimeException體系包括錯(cuò)誤的類型轉(zhuǎn)換、數(shù)組越界訪問和試圖訪問空指針等等。處理RuntimeException的原則是:如果出現(xiàn)RuntimeException,那么一定是程序員的錯(cuò)誤。例如,可以通過檢查數(shù)組下標(biāo)和數(shù)組邊界來避免數(shù)組越界訪問異常。
②其他非RuntimeException(IOException等等):這類異常一般是外部錯(cuò)誤,例如試圖從文件尾后讀取數(shù)據(jù)等,這并不是程序本身的錯(cuò)誤,而是在應(yīng)用環(huán)境中出現(xiàn)的外部錯(cuò)誤。
“如果出現(xiàn)RuntimeException異常,那么就一定是你的問題”是一條相當(dāng)有道理的規(guī)則。應(yīng)該通過檢測(cè)數(shù)組下標(biāo)是否越界來避免ArrayIndexOutOfBoundsException異常;應(yīng)該通過在使用變量之前檢測(cè)是否為空來杜絕NullPointerException異常的發(fā)生。
Java語言規(guī)范將派生于Error類或RuntimeException類的所有異常稱為未檢查(unchecked)異常,所有其他的異常稱為已檢查(checked)異常。這是兩個(gè)很有用的術(shù)語,在后面還會(huì)用到。編譯器將核查是否為所有的已檢查異常提供了異常處理器。

與c++對(duì)比:C++注釋:如果熟悉標(biāo)準(zhǔn)C++類庫中的異常層次結(jié)構(gòu),就一定會(huì)感到有些困惑。C++有兩個(gè)基本的異常類,一個(gè)是runtime_error;另一個(gè)是logic_error。logic_error類相當(dāng)于Java中的RuntimeException,它表示程序中的邏輯錯(cuò)誤;runtime_error類是所有由于不可預(yù)測(cè)的原因所引發(fā)的異常的基類。它相當(dāng)于Java中的非RuntimeException異常。

try關(guān)閉資源的一種寫法:
假設(shè)資源屬于一個(gè)實(shí)現(xiàn)了AutoCloseable接口的類,Java SE 7為這種代碼模式提供了一個(gè)很有用的快捷方式。AutoCloseable接口有一個(gè)方法:

void close() throws Exception

注釋:另外,還有一個(gè)Closeable接口。這是AutoCloseable的子接口,也包含一個(gè)close方法。不過,這個(gè)方法聲明為拋出一個(gè)IOException。

帶資源的try語句的最簡形式:

try(Resource res){ work with res }

try塊語句退出時(shí),會(huì)自動(dòng)調(diào)用res.close(),如:要讀取一個(gè)文件中所有單詞:

try{Scanner in = new Scanner(new FileInputStream("/xxx/xxx")) { while(in.hasNext()) { System.out.println(in.next()) } }

如果try塊拋出一個(gè)異常,而且close方法也拋出一個(gè)異常,這就會(huì)帶來一個(gè)難題。帶資源的try語句可以很好地處理這種情況。原來的異常會(huì)重新拋出,而close方法拋出的異常會(huì)“被抑制”。這些異常將自動(dòng)捕獲,并由addSuppressed方法增加到原來的異常。如果對(duì)這些異常感興趣,可以調(diào)用getSuppressed方法,它會(huì)得到從close方法拋出并被抑制的異常列表。 你肯定不想采用這種常規(guī)方式編程。只要需要關(guān)閉資源,就要盡可能使用帶資源的try語句。
注釋:帶資源的try語句自身也可以有catch子句和一個(gè)finally子句。這些子句會(huì)在關(guān)閉資源之后執(zhí)行。不過在實(shí)際中,一個(gè)try語句中加入這么多內(nèi)容可能不是一個(gè)好主意。

一下異常處理的技巧:
1.異常處理不能代替簡單的測(cè)試 作為一個(gè)示例,在這里編寫了一段代碼,試著上百萬次地對(duì)一個(gè)空棧進(jìn)行退棧操作。在實(shí)施退棧操作之前,首先要查看棧是否為空。

if(!s.empty()) s.pop();

接下來,強(qiáng)行進(jìn)行退棧操作。然后,捕獲EmptyStackException異常來告知我們不能這樣做。

try{ s.pop();} catch(EmptyStackException e) { }

在測(cè)試的機(jī)器上,調(diào)用isEmpty的版本運(yùn)行時(shí)間為646毫秒。捕獲EmptyStackException的版本運(yùn)行時(shí)間為21739毫秒。 可以看出,與執(zhí)行簡單的測(cè)試相比,捕獲異常所花費(fèi)的時(shí)間大大超過了前者,因此使用異常的基本規(guī)則是:只在異常情況下使用異常機(jī)制。

2.不要過分地細(xì)化異常 很多程序員習(xí)慣將每一條語句都分裝在一個(gè)獨(dú)立的try語句塊中。

PrintStream out; Stack s; for(int i = 0;i < 100;i++) { try{ n = s.pop(); } catch(EmptyStackException e) {} try { out.writeInt(n); } catch(IOException e) { //problem writing to file } }

這種編程方式將導(dǎo)致代碼量的急劇膨脹。首先看一下這段代碼所完成的任務(wù)。在這里,希望從棧中彈出100個(gè)數(shù)值,然后將它們存入一個(gè)文件中。(別考慮為什么,這只是一個(gè)“玩具”例子。)如果棧是空的,則不會(huì)變成非空狀態(tài);如果文件出現(xiàn)錯(cuò)誤,則也很難給予排除。出現(xiàn)上述問題后,這種編程方式無能為力。因此,有必要將整個(gè)任務(wù)包裝在一個(gè)try語句塊中,這樣,當(dāng)任何一個(gè)操作出現(xiàn)問題時(shí),整個(gè)任務(wù)都可以取消。
3.利用異常層次結(jié)構(gòu) 不要只拋出RuntimeException異常。
應(yīng)該尋找更加適當(dāng)?shù)淖宇惢騽?chuàng)建自己的異常類。 不要只捕獲Thowable異常,否則,會(huì)使程序代碼更難讀、更難維護(hù)。 考慮已檢查異常與未檢查異常的區(qū)別。已檢查異常本來就很龐大,不要為邏輯錯(cuò)誤拋出這些異常。(例如,反射庫的做法就不正確。調(diào)用者卻經(jīng)常需要捕獲那些早已知道不可能發(fā)生的異常。) 將一種異常轉(zhuǎn)換成另一種更加適合的異常時(shí)不要猶豫。例如,在解析某個(gè)文件中的一個(gè)整數(shù)時(shí),捕獲NumberFormatException異常,然后將它轉(zhuǎn)換成IOException或MySubsystemException的子類。

14.關(guān)于集合



斷言的使用

在默認(rèn)情況下,斷言被禁用。可以在運(yùn)行程序時(shí)用-enableassertions或-ea選項(xiàng)啟用它:

java -enableassertions MyApp

需要注意的是,在啟用或禁用斷言時(shí)不必重新編譯程序。啟用或禁用斷言是類加載器(class loader)的功能。當(dāng)斷言被禁用時(shí),類加載器將跳過斷言代碼,因此,不會(huì)降低程序運(yùn)行的速度。 也可以在某個(gè)類或某個(gè)包中使用斷言,例如:

這條命令將開啟MyClass類以及在com.mycompany.mylib包和它的子包中的所有類的斷言。選項(xiàng)-ea將開啟默認(rèn)包中的所有類的斷言。 也可以用選項(xiàng)-disableassertions或-da禁用某個(gè)特定類和包的斷言:

java -ea:MyClass -ea:com.mycompany.mylib..MyApp

這條命令將開啟MyClass類以及在com.mycompany.mylib包和它的子包中的所有類的斷言。選項(xiàng)-ea將開啟默認(rèn)包中的所有類的斷言。 也可以用選項(xiàng)-disableassertions或-da禁用某個(gè)特定類和包的斷言

日志

基本日志
下面從一個(gè)最簡單的例子開始。日志系統(tǒng)管理著一個(gè)名為Logger.global的默認(rèn)日志記錄器,可以用System.out替換它,并通過調(diào)用info方法記錄日志信息:

Logger.getGlobal().info("yes today");


高級(jí)日志
從前面已經(jīng)看到“虛擬日志”,下面繼續(xù)看一下企業(yè)級(jí)(industrial-strength)日志。在一個(gè)專業(yè)的應(yīng)用程序中,不要將所有的日志都記錄到一個(gè)全局日志記錄器中,而是可以自定義日志記錄器。調(diào)用getLogger方法可以創(chuàng)建或檢索記錄器:

private static final Logger myLogger = Logger.getLogger("com.example.demo.lambda");

與包名類似,日志記錄器名也具有層次結(jié)構(gòu)。事實(shí)上,與包名相比,日志記錄器的層次性更強(qiáng)。對(duì)于包來說,一個(gè)包的名字與其父包的名字之間沒有語義關(guān)系,但是日志記錄器的父與子之間將共享某些屬性。例如,如果對(duì)com.mycompany日志記錄器設(shè)置了日志級(jí)別,它的子記錄器也會(huì)繼承這個(gè)級(jí)別。
通常,有以下7個(gè)日志記錄器級(jí)別:
·SEVERE
·WARNING
·INFO
·CONFIG
·FINE
·FINER
·FINEST
在默認(rèn)情況下,只記錄前三個(gè)級(jí)別。也可以設(shè)置其他的級(jí)別。
myLogger.setLevel(Level.FINER);

泛型的使用

有時(shí),類或方法需要對(duì)類型變量加以約束。下面是一個(gè)典型的例子。我們要計(jì)算數(shù)組中的最小元素: 但是,這里有一個(gè)問題。請(qǐng)看一下min方法的代碼

class ArrayAlg{ public static<T>T min(T[]a) { if(a == null || a.length == 0) return null; T smallest = a[0]; for(int i = 0;i < a.length;i++) if(smallest.compreTo(a[i]) > 0) smallest = a[i]; return smallest; } }

內(nèi)部。變量smallest類型為T,這意味著它可以是任何一個(gè)類的對(duì)象。怎么才能確信T所屬的類有compareTo方法呢? 解決這個(gè)問題的方案是將T限制為實(shí)現(xiàn)了Comparable接口(只含一個(gè)方法compareTo的標(biāo)準(zhǔn)接口)的類。可以通過對(duì)類型變量T設(shè)置限定(bound)實(shí)現(xiàn)這一點(diǎn): 實(shí)際上Comparable接口本身就是一個(gè)泛型類型。目前,我們忽略其復(fù)雜性以及編譯器產(chǎn)生的警告

public static <T extends Comparable>T min(T[]a)..

現(xiàn)在,泛型的min方法只能被實(shí)現(xiàn)了Comparable接口的類(如String、Date等)的數(shù)組調(diào)用。由于Rectangle類沒有實(shí)現(xiàn)Comparable接口,所以調(diào)用min將會(huì)產(chǎn)生一個(gè)編譯錯(cuò)誤。

一個(gè)類型變量或通配符可以有多個(gè)限定,例如: 限定類型用“&”分隔,而逗號(hào)用來分隔類型變量。 在Java的繼承中,可以根據(jù)需要擁有多個(gè)接口超類型,但限定中至多有一個(gè)類。如果用一個(gè)類作為限定,它必須是限定列表中的第一個(gè)。

T extends Comparable & Serializable

計(jì)算8+88+888+8888+…的前12項(xiàng)和

public static void rnain(String args[]) { long sum = O,a = 8,itern = a,n = 12,i = l; for(i=l;i<=n;i++) { sum = surn+itern;item = itern*lO+a;}Systern.out.println(sum);}}

進(jìn)階

jvm內(nèi)存管理

通過對(duì)比會(huì)發(fā)現(xiàn)在JDK1.7版本中存在持久代內(nèi)存區(qū)域,而在JDK1.8版本中,該內(nèi)存區(qū)域被Meta Space取而代之了,元空間同樣是堆內(nèi)存的一部分,JVM為每個(gè)類加載器分配一塊內(nèi)存塊列表,進(jìn)行線性分配,塊的大小取決于類加載器的類型,sun/反射/代理對(duì)應(yīng)的類加載器塊會(huì)小一些,之前的版本會(huì)單獨(dú)卸載回收某個(gè)類,而現(xiàn)在則是GC過程中發(fā)現(xiàn)某個(gè)類加載器已經(jīng)具備回收的條件,則會(huì)將整個(gè)類加載器相關(guān)的元空間全部回收,這樣就可以減少內(nèi)存碎片,節(jié)省GC掃描和壓縮的時(shí)間。

Thread與虛擬機(jī)棧

JVM的內(nèi)存分布中,其中程序計(jì)數(shù) 器是比較小的一塊內(nèi)存,而且該部分內(nèi)存是不會(huì)出現(xiàn)任何溢出異常的,與線程創(chuàng)建、運(yùn)行、銷毀等關(guān)系比較大的是虛擬機(jī)棧內(nèi)存了,而且棧內(nèi)存劃分的大小將直接決定在一個(gè)JVM進(jìn)程中可以創(chuàng)建多少個(gè)線程,請(qǐng)看下面的例子:

ThreadCounter.java package com.wangwenjun.concurrent.chapter02;import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger;public class ThreadCounter extends Thread {final static AtomicInteger counter = new AtomicInteger(0);public static void main(String[] args){try{while (true){new ThreadCounter().start();}} catch (Throwable e){System.out.println("failed At=>" + counter.get());}}@Overridepublic void run(){try{System.out.println("The " + counter.getAndIncrement() + " thread be created.");TimeUnit.MINUTES.sleep(10);} catch (InterruptedException e){e.printStackTrace();}} }

在代碼中,我們不斷地創(chuàng)建線程,直到JVM再也沒有能力創(chuàng)建新的線程為止,我們通過設(shè)置棧內(nèi)存的大小來分析棧內(nèi)存大小對(duì)創(chuàng)建線程的影響,運(yùn)行上面的程序很容易出現(xiàn)系統(tǒng)死機(jī)的情況,通過測(cè)試數(shù)據(jù)的對(duì)比我們不難看出,線程的創(chuàng)建數(shù)量是隨著虛擬機(jī)棧內(nèi)存的增多而減少的,也就是一種反比關(guān)系

其實(shí)并不難理解,根據(jù)我們前面所學(xué)的知識(shí)可以得知,虛擬機(jī)棧內(nèi)存是線程私有的,也就是說每一個(gè)線程都會(huì)占有指定的內(nèi)存大小,我們粗略地認(rèn)為一個(gè)Java進(jìn)程的內(nèi)存大小為:堆內(nèi)存+線程數(shù)量*棧內(nèi)存。

不管是32位操作系統(tǒng)還是64位操作系統(tǒng),一個(gè)進(jìn)程的最大內(nèi)存是有限制的,比如32位的Windows操作系統(tǒng)所允許的最大進(jìn)程內(nèi)存為2GB,因此根據(jù)上面的公式很容易得出,線程數(shù)量與棧內(nèi)存的大小是反比關(guān)系,那么線程數(shù)量與堆內(nèi)存的大小關(guān)系呢?當(dāng)然也是反比關(guān)系,只不過堆內(nèi)存是基數(shù),而棧內(nèi)存是系數(shù)而已, 
堆內(nèi)存作為影響進(jìn)程內(nèi)存的基數(shù),它的增大對(duì)線程數(shù)量的影響也是反比關(guān)系,但是并沒有像棧內(nèi)存那樣明顯,線程數(shù)量與堆內(nèi)存大小的關(guān)系如圖2-9所示。

總結(jié)

以上是生活随笔為你收集整理的【学习笔记】java基础核心总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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