阻塞隊(duì)列
隊(duì)列:先進(jìn)先出的一種數(shù)據(jù)結(jié)構(gòu)
阻塞隊(duì)列就是在數(shù)據(jù)為空的時(shí)候动看,如果從隊(duì)列中獲取數(shù)據(jù)將被阻塞,如果隊(duì)列滿了的話往隊(duì)列里面插入數(shù)據(jù)將會被阻塞洞慎。
有界與無界
有界隊(duì)列就是隊(duì)列的大小是固定的
無界隊(duì)列就是隊(duì)列滿了之后可以進(jìn)行擴(kuò)容
延時(shí)阻塞隊(duì)列
DelayQueue,延時(shí)獲取痛单,如果延時(shí)沒有到,那么將會被阻塞
可以
線程池的參數(shù)
核心線程數(shù)
最大線程數(shù)
- IO密集型
IO密集型一般最大線程數(shù)是cpu核心數(shù)2
IO密集型一般不是特別占用cpu的資源劲腿,有網(wǎng)絡(luò)操作和磁盤操作旭绒。當(dāng)進(jìn)行一個(gè)網(wǎng)絡(luò)操作的時(shí)候,線程需要等待網(wǎng)絡(luò)數(shù)據(jù)的返回谆棱,這個(gè)時(shí)候線程會交出執(zhí)行權(quán)快压,所以我們設(shè)置cpu核心數(shù)2的話會保證cpu的資源不會被浪費(fèi)。 - CPU密集型
CPU密集型一般最大線程數(shù)是cpu核心數(shù)+1
CPU密集型一般是頻繁的數(shù)據(jù)操作垃瞧,操作系統(tǒng)中有內(nèi)存和磁盤存儲蔫劣,操作系統(tǒng)將磁盤存儲的一部分拿出來作為虛擬內(nèi)存,如果一個(gè)線程要使用虛擬內(nèi)存和內(nèi)存中的數(shù)據(jù)的時(shí)候个从,由于虛擬內(nèi)存獲取數(shù)據(jù)的速度遠(yuǎn)遠(yuǎn)沒有從內(nèi)存獲取數(shù)據(jù)快脉幢,這個(gè)時(shí)候我們就可以再啟動(dòng)額外的線程來執(zhí)行下一個(gè)數(shù)據(jù)操作。 - 混合型
如果CPU密集型和IO密集型花的時(shí)間差不多嗦锐,那么可以進(jìn)行拆分為2個(gè)線程池
如果差距很大的話嫌松,以時(shí)間花費(fèi)大的為準(zhǔn)
線程存活時(shí)間
一般來說當(dāng)線程的run方法執(zhí)行完了之后線程就會被銷毀,那么如何讓線程按照存活時(shí)間奕污?
我們從阻塞隊(duì)列中獲取數(shù)據(jù)萎羔,如果沒有數(shù)據(jù)線程會被阻塞,他就不會死亡
拒絕策略
當(dāng)核心線程數(shù)碳默,阻塞隊(duì)列贾陷,最大線程數(shù)已滿的話線程池有拒絕任務(wù)的策略
1.拋異常
立馬拋出一場
2.拋棄阻塞隊(duì)列最前面的
刪除掉隊(duì)列中最老的那一個(gè)任務(wù)
3.拋棄現(xiàn)有的任務(wù)
直接把現(xiàn)在要提交的任務(wù)刪掉
4.交給提交任務(wù)的線程處理
如果主線程提交的任務(wù),那么就讓主線程來執(zhí)行嘱根。
線程池關(guān)閉
shutDown 將還未執(zhí)行的線程銷毀
shutDownNow 使用中斷策略interrupt髓废,銷毀執(zhí)行中的線程以及未執(zhí)行的線程
線程池的原理
1.當(dāng)線程池中的線程還沒有達(dá)到核心線程數(shù),那么就創(chuàng)建線程來執(zhí)行任務(wù)
2.如果線程池中的線程還沒有達(dá)到核心線程數(shù)该抒,那么就向阻塞隊(duì)列中插入
3.如果阻塞隊(duì)列也滿了慌洪,那么就看看是否達(dá)到最大線程數(shù),如果沒有達(dá)到最大線程數(shù),那就開啟線程執(zhí)行任務(wù)
4.如果達(dá)到了最大線程數(shù)冈爹,那么就使用拒絕策略
零拷貝
用戶空間和內(nèi)核空間的概念
為了保證我們的應(yīng)用程序訪問不到操作系統(tǒng)里面的數(shù)據(jù)涌攻,并且不篡改操作系統(tǒng)的數(shù)據(jù),操作系統(tǒng)將內(nèi)存分為了2部分频伤,一部分是操作系統(tǒng)內(nèi)存癣漆,一部分是用戶內(nèi)存,用戶內(nèi)存無法訪問操作系統(tǒng)內(nèi)存剂买。
但是,如果我們程序需要訪問網(wǎng)絡(luò)的時(shí)候癌蓖,需要操作系統(tǒng)底層調(diào)用網(wǎng)卡等設(shè)備瞬哼,我們需要在用戶空間里面將請求參數(shù)復(fù)制到操作系統(tǒng)內(nèi)存中,當(dāng)獲取到網(wǎng)絡(luò)結(jié)果之后需要將返回?cái)?shù)據(jù)從操作系統(tǒng)內(nèi)存拷貝到用戶內(nèi)存中
為了避免兩次無用的拷貝租副,操作系統(tǒng)允許我們的應(yīng)用程序在操作系統(tǒng)內(nèi)存中申請一塊臨時(shí)空間坐慰,我們只需要將請求數(shù)據(jù)放到申請的操作系統(tǒng)空間內(nèi),當(dāng)網(wǎng)絡(luò)數(shù)據(jù)返回的時(shí)候會寫入到我們申請的空間內(nèi)用僧。
DMA
磁盤操作 操作系統(tǒng)會交給磁盤控制器
網(wǎng)絡(luò)操作 操作系統(tǒng)會交給網(wǎng)絡(luò)控制器
單機(jī)緩存系統(tǒng)
1.通過add和get方法存入和獲取數(shù)據(jù)结胀,當(dāng)add的時(shí)候數(shù)據(jù)也要放入延時(shí)隊(duì)列中。
2.開啟一個(gè)子線程獲取延時(shí)隊(duì)列的數(shù)據(jù)责循,如果拿到數(shù)據(jù)了說明時(shí)間到了糟港,過期了我們就需要將數(shù)據(jù)刪除,如果沒有拿到說明還未過期
public class Memory {
private DelayQueue<Data> delayQueue;
private ConcurrentHashMap<String,Object> hashMap=new ConcurrentHashMap<>();
private final Thread thread;
private Memory(){
delayQueue=new DelayQueue<>();
thread = new Thread(new CheckRunnable(this));
thread.start();
}
private static Memory memory;
public static Memory getInstance(){
if (memory==null){
synchronized (Memory.class){
if (memory==null){
memory=new Memory();
}
}
}
return memory;
}
public <T>T get(String key){
return (T) hashMap.get(key);
}
public <T> void add(String key,T value,long time){
delayQueue.add(new Data(key,time));
hashMap.put(key,value);
}
static class CheckRunnable implements Runnable{
private Memory memory;
public CheckRunnable(Memory memory){
this.memory=memory;
}
@Override
public void run() {
Thread thread = Thread.currentThread();
while (!thread.isInterrupted()){
Data take = memory.delayQueue.poll();
if (take!=null) {
if (memory.hashMap.containsKey(take.getKey())) {
System.out.println("remove");
memory.hashMap.remove(take.getKey());
}
}
}
}
}
public void shutDown(){
thread.interrupt();
hashMap.clear();
}
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
super.run();
final Memory instance = Memory.getInstance();
instance.<String>add("name","Z",10000);
instance.<Integer>add("age",18,8000);
int count=1;
while (true){
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(2000*count);
String name = instance.<String>get("name");
Integer age = instance.<Integer>get("age");
System.out.println("name="+name);
System.out.println("age="+age);
count++;
}
}
}.start();
}
}
public class Data implements Delayed {
private String key;
private long time;
public Data(String key, long timeout){
this.time=timeout+System.currentTimeMillis();
this.key=key;
}
public String getKey(){
return key;
}
@Override
public long getDelay(TimeUnit unit) {
return this.time-System.currentTimeMillis();
}
@Override
public int compareTo(Delayed o) {
if (this.getDelay(TimeUnit.MILLISECONDS)>o.getDelay(TimeUnit.MILLISECONDS)){
return 1;
}else if (this.getDelay(TimeUnit.MILLISECONDS)<o.getDelay(TimeUnit.MILLISECONDS)){
return -1;
}
return 0;
}
}