java 堆與棧
1、Java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)候醒,類的對象從堆中分配空間能颁。這些對象通過new等指令建立,通過垃圾回收器來銷毀倒淫。
2伙菊、堆的優(yōu)勢是可以動(dòng)態(tài)地分配內(nèi)存空間,需要多少內(nèi)存空間不必事先告訴編譯器,因?yàn)樗窃谶\(yùn)行時(shí)動(dòng)態(tài)分配的镜硕。但缺點(diǎn)是运翼,由于需要在運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存,所以存取速度較慢兴枯。
1南蹂、 棧中主要存放一些基本數(shù)據(jù)類型的變量(byte,short念恍,int六剥,long,float峰伙,double疗疟,boolean,char)和對象的引用瞳氓。
2策彤、棧的優(yōu)勢是,存取速度比堆快匣摘,棧數(shù)據(jù)可以共享店诗。但缺點(diǎn)是,存放在棧中的數(shù)據(jù)占用多少內(nèi)存空間需要在編譯時(shí)確定下來音榜,缺乏靈活性庞瘸。
String str1 = new String("abc");
String str2 = "abc";
第一種使用new來創(chuàng)建的對象,它存放在堆中赠叼。每調(diào)用一次就創(chuàng)建一個(gè)新的對象擦囊。
第二種是先在棧中創(chuàng)建對象的引用str2,然后查找棧中有沒有存放“abc”嘴办,如果沒有瞬场,則將“abc”存放進(jìn)棧,并將str2指向“abc”涧郊,如果已經(jīng)有“abc”贯被, 則直接將str2指向“abc”。
Java 數(shù)組與鏈表
數(shù)組是一種連續(xù)存儲(chǔ)線性結(jié)構(gòu)妆艘,元素類型相同彤灶,大小相等,數(shù)組是多維的双仍,通過使用整型索引值來訪問他們的元素枢希,數(shù)組尺寸不能改變。
數(shù)組的優(yōu)點(diǎn):存取速度快
數(shù)組的缺點(diǎn):事先必須知道數(shù)組的長度朱沃、插入刪除元素很慢、
空間通常是有限制的、需要大塊連續(xù)的內(nèi)存塊逗物、插入刪除元素的效率很低
2搬卒、鏈表是有data和指向下一個(gè)數(shù)據(jù)的指針地址兩部分組成
鏈表的優(yōu)點(diǎn): 插入刪除速度快、 內(nèi)存利用率高翎卓,不會(huì)浪費(fèi)內(nèi)存
契邀、大小沒有固定,拓展很靈活失暴。
鏈表的缺點(diǎn):不能隨機(jī)查找坯门,必須從第一個(gè)開始遍歷,查找效率低逗扒。
HashMap的原理
HashMap實(shí)現(xiàn)了Map接口古戴,Map接口對鍵值對進(jìn)行映射。Map中不允許重復(fù)的鍵矩肩。Map接口有兩個(gè)基本的實(shí)現(xiàn)现恼,HashMap和TreeMap。TreeMap保存了對象的排列次序黍檩,而HashMap則不能叉袍。HashMap允許鍵和值為null。HashMap是非synchronized的刽酱,
哈希表結(jié)構(gòu):結(jié)合數(shù)組結(jié)構(gòu)和鏈表結(jié)構(gòu)的優(yōu)點(diǎn)喳逛,從而實(shí)現(xiàn)了查詢和修改效率高,插入和刪除效率也高的一種數(shù)據(jù)結(jié)構(gòu)
HashMap 為何默認(rèn)容量為16棵里?
HashMap的默認(rèn)長度為16,是為了降低hash碰撞的幾率艺配。
/*
將hashcode換成鏈表數(shù)組中的下標(biāo)
X % 2^n = X & (2^n – 1)
位運(yùn)算(&)效率要比代替取模運(yùn)算(%)高很多
**/
static int indexFor(int h, int length) {
return h & (length-1);
}
HashMap和Hashtable區(qū)別?
HashMap:
(1)由數(shù)組+鏈表組成的,基于哈希表的Map實(shí)現(xiàn)衍慎,數(shù)組是HashMap的主體转唉,
鏈表則是主要為了解決哈希沖突而存在的。
(2)不是線程安全的稳捆,HashMap可以接受為null的鍵(key)和值(value)赠法。
(3)HashMap重新計(jì)算hash值
Hashtable:
(1)Hashtable 是一個(gè)散列表,它存儲(chǔ)的內(nèi)容是鍵值對(key-value)映射。
(2)Hashtable 的函數(shù)都是同步的郎哭,這意味著它是線程安全的瑟捣。它的key、value都不可以為null侧纯。
(3)HashTable直接使用對象的hashCode。
雙重檢查鎖甲脏,為什么要加volatile
1眶熬、保證可見性妹笆。使用 volatile 定義的變量,將會(huì)保證對所有線程的可見性娜氏。
2拳缠、禁止指令重排序優(yōu)化。
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) { // 此處為類級別的鎖
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
CAS
- Compare and Swap 比較并交換
- 內(nèi)存地址的值V贸弥,舊的預(yù)期的值A(chǔ)窟坐,要修改的新值B。只要當(dāng)V與A相等時(shí)绵疲,才會(huì)將V修改為新的值B哲鸳。
- Unsafe將cas編譯成一條cpu指令,沒有函數(shù)調(diào)用
- aba問題:當(dāng)前值可能是變?yōu)閎后再變?yōu)閍盔憨,此a非彼a徙菠,通過加版本號能解決
- 非阻塞同步:沒有掛起喚醒操作,多個(gè)線程同時(shí)修改一個(gè)共享變量時(shí)般渡,只有一個(gè)線程會(huì)成功懒豹,其余失敗,它們可以選擇輪詢驯用。
ReentrantLock和synchronized的區(qū)別
- ReentrantLock 需要顯示的釋放鎖脸秽,lock.unlock()。
- ReentrantLock 構(gòu)造器傳入true實(shí)現(xiàn)公平鎖蝴乔。
- ReentrantLock 等待可中斷记餐,當(dāng)持有鎖的線程長期不釋放鎖的時(shí)候,正在等待的線程可以選擇放棄等待薇正,改為處理其他事情片酝。
- ReentrantLock 可以綁定多個(gè)條件,多次調(diào)用newCondition()同時(shí)綁定多個(gè)Condition對象挖腰。
進(jìn)程與線程的區(qū)別
1雕沿、進(jìn)程是表示資源分配的基本單位,又是調(diào)度運(yùn)行的基本單位猴仑。
2审轮、線程是進(jìn)程中執(zhí)行運(yùn)算的最小單位,亦即執(zhí)行處理機(jī)調(diào)度的基本單位辽俗。
線程的優(yōu)點(diǎn):
(1)易于調(diào)度疾渣。
(2)提高并發(fā)性。通過線程可方便有效地實(shí)現(xiàn)并發(fā)性崖飘。進(jìn)程可創(chuàng)建多個(gè)線程來執(zhí)行同一程序的不同部分榴捡。
(3)開銷少。創(chuàng)建線程比創(chuàng)建進(jìn)程要快朱浴,所需開銷很少吊圾。达椰。
(4)利于充分發(fā)揮多處理器的功能。通過創(chuàng)建多線程進(jìn)程(即一個(gè)進(jìn)程可具有兩個(gè)或更多個(gè)線程)街夭,每個(gè)線程在一個(gè)處理器上運(yùn)行砰碴,從而實(shí)現(xiàn)應(yīng)用程序的并發(fā)性躏筏,使每個(gè)處理器都得到充分運(yùn)行板丽。
進(jìn)程和線程的關(guān)系:
(1)一個(gè)線程只能屬于一個(gè)進(jìn)程,而一個(gè)進(jìn)程可以有多個(gè)線程趁尼,但至少有一個(gè)線程埃碱。
(2)資源分配給進(jìn)程,同一進(jìn)程的所有線程共享該進(jìn)程的所有資源酥泞。
(3)處理機(jī)分給線程砚殿,即真正在處理機(jī)上運(yùn)行的是線程。
(4)線程在執(zhí)行過程中芝囤,需要協(xié)作同步似炎。不同進(jìn)程的線程間要利用消息通信的辦法實(shí)現(xiàn)同步。
內(nèi)存回收機(jī)制與GC算法
內(nèi)存判定對象可回收有兩種機(jī)制:
1悯姊、引用計(jì)數(shù)算法:給對象中添加一個(gè)引用計(jì)數(shù)器羡藐,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值就加1悯许;當(dāng)引用失效時(shí)仆嗦,計(jì)數(shù)器值就減1;任何時(shí)刻計(jì)數(shù)器為0的對象就是不可能再被使用的先壕。然而在主流的Java虛擬機(jī)里未選用引用計(jì)數(shù)算法來管理內(nèi)存瘩扼,主要原因是它難以解決對象之間相互循環(huán)引用的問題,所以出現(xiàn)了另一種對象存活判定算法垃僚。
2集绰、可達(dá)性分析法:通過一系列被稱為『GCRoots』的對象作為起始點(diǎn),從這些節(jié)點(diǎn)開始向下搜索谆棺,搜索所走過的路徑稱為引用鏈栽燕,當(dāng)一個(gè)對象到GC Roots沒有任何引用鏈相連時(shí),則證明此對象是不可用的包券。
3 纫谅、可作為GC Roots的對象:
- 虛擬機(jī)棧中引用的對象,主要是指棧幀中的本地變量
- 本地方法棧中Native方法引用的對象
- 方法區(qū)中類靜態(tài)屬性引用的對象
- 方法區(qū)中常量引用的對象
GC回收算法有以下四種:
分代收集算法:是當(dāng)前商業(yè)虛擬機(jī)都采用的一種算法溅固,根據(jù)對象存活周期的不同付秕,將Java堆劃分為新生代和老年代,并根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?/p>
新生代:大批對象死去侍郭,只有少量存活询吴。使用『復(fù)制算法』掠河,只需復(fù)制少量存活對象即可。
復(fù)制算法: 把可用內(nèi)存按容量劃分為大小相等的兩塊猛计,每次只使用其中的一塊唠摹。當(dāng)這一塊的內(nèi)存用盡后,把還存活著的對象『復(fù)制』到另外一塊上面奉瘤,再將這一塊內(nèi)存空間一次清理掉勾拉。實(shí)現(xiàn)簡單,運(yùn)行高效盗温。在對象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作藕赞,效率將會(huì)變低。
老年代:對象存活率高卖局。使用『標(biāo)記—清理算法』或者『標(biāo)記—整理算法』斧蜕,只需標(biāo)記較少的回收對象即可。
標(biāo)記-清除算法: 首先『標(biāo)記』出所有需要回收的對象砚偶,然后統(tǒng)一『清除』所有被標(biāo)記的對象批销。標(biāo)記和清除兩個(gè)過程的效率都不高,清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片染坯,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過程中需要分配較大對象時(shí)均芽,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。
標(biāo)記-整理算法: 首先『標(biāo)記』出所有需要回收的對象酒请,然后進(jìn)行『整理』骡技,使得存活的對象都向一端移動(dòng),最后直接清理掉端邊界以外的內(nèi)存羞反。標(biāo)記整理算法會(huì)將所有的存活對象移動(dòng)到一端布朦,并對不存活對象進(jìn)行處理,因此其不會(huì)產(chǎn)生內(nèi)存碎片昼窗。
Http和Https區(qū)別
HTTP:是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議是趴,是一個(gè)客戶端和服務(wù)器端請求和應(yīng)答的標(biāo)準(zhǔn)(TCP),用于從WWW服務(wù)器傳輸超文本到本地瀏覽器的傳輸協(xié)議澄惊,它可以使瀏覽器更加高效唆途,使網(wǎng)絡(luò)傳輸減少。
HTTPS:是以安全為目標(biāo)的HTTP通道掸驱,簡單講是HTTP的安全版肛搬,即HTTP下加入SSL層,HTTPS的安全基礎(chǔ)是SSL毕贼,因此加密的詳細(xì)內(nèi)容就需要SSL温赔。
HTTPS協(xié)議的主要作用可以分為兩種:一種是建立一個(gè)信息安全通道,來保證數(shù)據(jù)傳輸?shù)陌踩硌ⅲ涣硪环N就是確認(rèn)網(wǎng)站的真實(shí)性陶贼。
HTTPS和HTTP的區(qū)別主要如下:
1啤贩、https協(xié)議需要到ca申請證書,一般免費(fèi)證書較少拜秧,因而需要一定費(fèi)用痹屹。
2、http是超文本傳輸協(xié)議枉氮,信息是明文傳輸志衍,https則是具有安全性的ssl加密傳輸協(xié)議。
3嘲恍、http和https使用的是完全不同的連接方式足画,用的端口也不一樣雄驹,前者是80佃牛,后者是443
4、http的連接很簡單医舆,是無狀態(tài)的俘侠;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議蔬将,比http協(xié)議安全爷速。
java線程池
線程池:降低資源消耗,提高響應(yīng)速度霞怀,提高線程的可管理性惫东。
- 1.緩存線程池 (newCachedThreadPool)
/**
*緩存線程池.
* (長度無限制)
* 執(zhí)行流程:
* 1. 判斷線程池是否存在空閑線程
* 2. 存在則使用
* 3. 不存在,則創(chuàng)建線程 并放入線程池, 然后使用
* */
ExecutorService service = Executors.newCachedThreadPool();
//向線程池中 加入 新的任務(wù)
service.execute(new Runnable() {
@Override public void run() {
System.out.println("線程的名稱:"+Thread.currentThread().getName());
}
});
service.execute(new Runnable() {
@Override public void run() {
System.out.println("線程的名稱:"+Thread.currentThread().getName());
}
});
service.execute(new Runnable() {
@Override public void run() {
System.out.println("線程的名稱:"+Thread.currentThread().getName());
}
});
- 2.定長線程池 (newFixedThreadPool)
/**
* 定長線程池.(長度是指定的數(shù)值)
* 執(zhí)行流程:
* 1. 判斷線程池是否存在空閑線程
* 2. 存在則使用
* 3. 不存在空閑線程,且線程池未滿的情況下,則創(chuàng)建線程 并放入線程池, 然后使用
* 4. 不存在空閑線程,且線程池已滿的情況下,則等待線程池存在空閑線程
* */
ExecutorService service = Executors.newFixedThreadPool(2);
service.execute(new Runnable() {
@Override
public void run() {
System.out.println("線程的名稱:" + Thread.currentThread().getName());
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println("線程的名稱:" + Thread.currentThread().getName());
}
});
- 3.單線程線程池 (newSingleThreadExecutor)
/**
* 單線程線程池.
* 執(zhí)行流程:
* 1. 判斷線程池 的那個(gè)線程 是否空閑
* 2. 空閑則使用
* 3. 不空閑,則等待 池中的單個(gè)線程空閑后 使用
* */
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(new Runnable() {
@Override
public void run() {
System.out.println("線程的名稱:" + Thread.currentThread().getName());
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println("線程的名稱:" + Thread.currentThread().getName());
}
});
- 4.周期性任務(wù)定長線程池 (newScheduledThreadPool)
/**
* 周期任務(wù) 定長線程池.
* 執(zhí)行流程:
* 1. 判斷線程池是否存在空閑線程
* 2. 存在則使用
* 3. 不存在空閑線程,且線程池未滿的情況下,則創(chuàng)建線程 并放入線程池, 然后使用
* 4. 不存在空閑線程,且線程池已滿的情況下,則等待線程池存在空閑線程
*
* 周期性任務(wù)執(zhí)行時(shí):
* 定時(shí)執(zhí)行, 當(dāng)某個(gè)時(shí)機(jī)觸發(fā)時(shí), 自動(dòng)執(zhí)行某任務(wù) .
* */
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
/**
* 定時(shí)執(zhí)行
* 參數(shù)1. runnable類型的任務(wù)
* 參數(shù)2. 時(shí)長數(shù)字
* 參數(shù)3. 時(shí)長數(shù)字的單位
* */
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println(" hello world ");
}
}, 5, TimeUnit.SECONDS);
/**
* 周期執(zhí)行
* 參數(shù)1. runnable類型的任務(wù)
* 參數(shù)2. 時(shí)長數(shù)字(延遲執(zhí)行的時(shí)長)
* 參數(shù)3. 周期時(shí)長(每次執(zhí)行的間隔時(shí)間)
* 參數(shù)4. 時(shí)長數(shù)字的單位 */
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(" hello world ");
}
}, 5, 2, TimeUnit.SECONDS);