Android進(jìn)程管理篇(三)-進(jìn)程adj算法

一、背景介紹

Android在設(shè)計(jì)上是有真后臺(tái)的朝卒,理論上是希望應(yīng)用程序能盡可能長(zhǎng)地存活证逻,這樣用戶體驗(yàn)會(huì)更好,畢竟熱啟動(dòng)肯定比冷啟動(dòng)要快抗斤。但是系統(tǒng)內(nèi)存是有限的瑟曲,不可能讓所有應(yīng)用一視同仁地存活著,所以需要系統(tǒng)制定一套規(guī)則來(lái)統(tǒng)一管理豪治,決定在什么場(chǎng)景下哪些應(yīng)用要保證它的使用體驗(yàn),哪些應(yīng)用需要被殺掉騰出內(nèi)存空間來(lái)扯罐。在Android framework層中负拟,ActivityManagerService簡(jiǎn)稱AMS,就主要負(fù)責(zé)進(jìn)程的調(diào)度和管理歹河。

二掩浙、規(guī)則介紹

那具體怎么管理?最簡(jiǎn)單的想法就是通過(guò)優(yōu)先級(jí)來(lái)控制秸歧。

那么按優(yōu)先級(jí)來(lái)劃分進(jìn)程厨姚,粗分為5類:

前臺(tái)進(jìn)程(Foreground process):用戶當(dāng)前操作所必需的進(jìn)程。

  • 擁有用戶正在交互的 Activity(已調(diào)用onResume())
  • 擁有某個(gè) Service键菱,后者綁定到用戶正在交互的 Activity
  • 擁有正在“前臺(tái)”運(yùn)行的 Service(服務(wù)已調(diào)用 startForeground())
  • 擁有正執(zhí)行一個(gè)生命周期回調(diào)的 Service(onCreate()谬墙、onStart() 或 onDestroy())
  • 擁有正執(zhí)行其 onReceive() 方法的 BroadcastReceiver

可見(jiàn)進(jìn)程(Visible process): 沒(méi)有任何前臺(tái)組件、但仍會(huì)影響用戶在屏幕上所見(jiàn)內(nèi)容的進(jìn)程。

  • 擁有不在前臺(tái)拭抬、但仍對(duì)用戶可見(jiàn)的 Activity(已調(diào)用onPause())部默。
  • 擁有綁定到可見(jiàn)(或前臺(tái))Activity 的 Service

服務(wù)進(jìn)程(Service process): 盡管服務(wù)進(jìn)程與用戶所見(jiàn)內(nèi)容沒(méi)有直接關(guān)聯(lián),但是它們通常在執(zhí)行一些用戶關(guān)心的操作(例如造虎,在后臺(tái)播放音樂(lè)或從網(wǎng)絡(luò)下載數(shù)據(jù))傅蹂。

  • 正在運(yùn)行startService()方法啟動(dòng)的服務(wù),且不屬于上述兩個(gè)更高類別進(jìn)程的進(jìn)程算凿。

后臺(tái)進(jìn)程(Background process) 后臺(tái)進(jìn)程對(duì)用戶體驗(yàn)沒(méi)有直接影響份蝴,系統(tǒng)可能隨時(shí)終止它們,以回收內(nèi)存供前臺(tái)進(jìn)程氓轰、可見(jiàn)進(jìn)程或服務(wù)進(jìn)程使用婚夫。

  • 對(duì)用戶不可見(jiàn)的Activity的進(jìn)程(已調(diào)用Activity的onStop()方法)

空進(jìn)程(Empty process)只有一個(gè)進(jìn)程殼子,存在的意義僅僅是縮短啟動(dòng)時(shí)間戒努。

  • 不含任何活動(dòng)應(yīng)用組件的進(jìn)程

當(dāng)然系統(tǒng)劃分不會(huì)這么糙请敦,分別通過(guò)adj和procState來(lái)給進(jìn)程貼優(yōu)先級(jí)標(biāo)簽,其中adj定義在ProcessList.java中储玫,procState定義在ActivityManager.java中侍筛,如下所示:

ADJ:

ADJ級(jí)別 取值 含義
NATIVE_ADJ -1000 native進(jìn)程
SYSTEM_ADJ -900 僅指system_server進(jìn)程
PERSISTENT_PROC_ADJ -800 系統(tǒng)persistent進(jìn)程
PERSISTENT_SERVICE_ADJ -700 關(guān)聯(lián)著系統(tǒng)或persistent進(jìn)程
FOREGROUND_APP_ADJ 0 前臺(tái)進(jìn)程
VISIBLE_APP_ADJ 100 可見(jiàn)進(jìn)程
PERCEPTIBLE_APP_ADJ 200 可感知進(jìn)程,比如后臺(tái)音樂(lè)播放
BACKUP_APP_ADJ 300 備份進(jìn)程
HEAVY_WEIGHT_APP_ADJ 400 重量級(jí)進(jìn)程
SERVICE_ADJ 500 服務(wù)進(jìn)程
HOME_APP_ADJ 600 Home進(jìn)程
PREVIOUS_APP_ADJ 700 上一個(gè)進(jìn)程
SERVICE_B_ADJ 800 B List中的Service
CACHED_APP_MIN_ADJ 900 不可見(jiàn)進(jìn)程的adj最小值
CACHED_APP_MAX_ADJ 906 不可見(jiàn)進(jìn)程的adj最大值

ProcState:

state級(jí)別 取值 解釋
PROCESS_STATE_CACHED_EMPTY 16 進(jìn)程處于cached狀態(tài)撒穷,且為空進(jìn)程
PROCESS_STATE_CACHED_ACTIVITY_CLIENT 15 進(jìn)程處于cached狀態(tài)匣椰,且為另一個(gè)cached進(jìn)程(內(nèi)含Activity)的client進(jìn)程
PROCESS_STATE_CACHED_ACTIVITY 14 進(jìn)程處于cached狀態(tài),且內(nèi)含Activity
PROCESS_STATE_LAST_ACTIVITY 13 后臺(tái)進(jìn)程端礼,且擁有上一次顯示的Activity
PROCESS_STATE_HOME 12 后臺(tái)進(jìn)程禽笑,且擁有home Activity
PROCESS_STATE_RECEIVER 11 后臺(tái)進(jìn)程,且正在運(yùn)行receiver
PROCESS_STATE_SERVICE 10 后臺(tái)進(jìn)程蛤奥,且正在運(yùn)行service
PROCESS_STATE_HEAVY_WEIGHT 9 后臺(tái)進(jìn)程佳镜,但無(wú)法執(zhí)行restore,因此盡量避免kill該進(jìn)程
PROCESS_STATE_BACKUP 8 后臺(tái)進(jìn)程凡桥,正在運(yùn)行backup/restore操作
PROCESS_STATE_IMPORTANT_BACKGROUND 7 對(duì)用戶很重要的進(jìn)程蟀伸,用戶不可感知其存在
PROCESS_STATE_IMPORTANT_FOREGROUND 6 對(duì)用戶很重要的進(jìn)程,用戶可感知其存在
PROCESS_STATE_TOP_SLEEPING 5 與PROCESS_STATE_TOP一樣缅刽,但此時(shí)設(shè)備正處于休眠狀態(tài)
PROCESS_STATE_FOREGROUND_SERVICE 4 擁有一個(gè)前臺(tái)Service
PROCESS_STATE_BOUND_FOREGROUND_SERVICE 3 擁有一個(gè)前臺(tái)Service啊掏,且由系統(tǒng)綁定
PROCESS_STATE_TOP 2 擁有當(dāng)前用戶可見(jiàn)的top Activity
PROCESS_STATE_PERSISTENT_UI 1 persistent系統(tǒng)進(jìn)程,并正在執(zhí)行UI操作
PROCESS_STATE_PERSISTENT 0 persistent系統(tǒng)進(jìn)程
PROCESS_STATE_NONEXISTENT -1 不存在的進(jìn)程
三衰猛、調(diào)度策略分析

標(biāo)簽定義好了迟蜜,那么如何去為進(jìn)程設(shè)置adj和procState值,以及如何決定在哪些場(chǎng)景下殺掉哪些進(jìn)程呢啡省?那么來(lái)看看AMS的調(diào)度策略

AMS中與adj相關(guān)的有三個(gè)方法:

  • updateOomAdjLocked:在進(jìn)程組件生命周期變化時(shí)更新adj娜睛,然后分別執(zhí)行以下兩個(gè)方法
  • computeOomAdjLocked:計(jì)算adj
  • applyOomAdjLocked:應(yīng)用adj

updateOomAdjLocked只是一個(gè)調(diào)用的入口而已髓霞,實(shí)際干活的是computeOomAdjLocked和applyOomAdjLocked,那么來(lái)分別看看微姊,代碼不貼了酸茴,總結(jié)下主要的功能點(diǎn)。

updateOomAdjLocked有無(wú)參兢交、一參薪捍、五參三個(gè)重載方法,主要看看無(wú)參方法:

final void updateOomAdjLocked() {

LruProcesses以Lru的方式保存活著的進(jìn)程

emptyProcessLimit 與 cachedProcessLimit
設(shè)置好empty和cache的數(shù)量配喳,可以設(shè)置cache和empty的總數(shù)mProcessLimit(默認(rèn)是32酪穿,2G內(nèi)存可能調(diào)整為16),一般來(lái)說(shuō)他倆各占一半晴裹。再往下是初始化一些變量的操作被济,這里要重點(diǎn)注意numSlots所表達(dá)的意思。ProcessList.CACHED_APP_MAX_ADJ和Process.CACHED_APP_MIN_ADJ常量系統(tǒng)默認(rèn)的值分別為906和900涧团,表示的是后臺(tái)進(jìn)程和empty進(jìn)程分配的值是在900至906之間只磷,共有7個(gè)值。numSloas計(jì)算過(guò)程中除以2是因?yàn)槊總€(gè)槽配置到進(jìn)程包含cache進(jìn)程和empty進(jìn)程兩種泌绣,兩種進(jìn)程需用不同adj值表示钮追,所以每個(gè)槽包含兩個(gè)adj值的分配空間,所以需要除以二阿迈,計(jì)算出來(lái)的numSlots值為3元媚。emptyFactor表示每個(gè)槽中需要放置幾個(gè)empty進(jìn)程,是根據(jù)當(dāng)前empty進(jìn)程總數(shù)決定的苗沧,cachedFactor即是表示需要放置幾個(gè)后臺(tái)進(jìn)程到每個(gè)槽中刊棕。為便于理解,結(jié)合后面代碼邏輯舉例來(lái)講待逞,比如后臺(tái)此時(shí)有15個(gè)cahcedProcess(后臺(tái)進(jìn)程)和12個(gè)emptyProcess甥角,則會(huì)將15/3=5個(gè)cachedProcess設(shè)置到在第一個(gè)槽(可分配900,901這兩個(gè)oom_adj值)中识樱,oom_adj設(shè)置為900蜈膨;將12/3=4個(gè)emptyProcess設(shè)置在第一槽,oom_adj值設(shè)置為901牺荠;然后再設(shè)置5個(gè)cachedProcess和4個(gè)emptyProcess的oom_adj值分別為902和903,即第二個(gè)槽驴一。

從LruProcesses最新加入的元素開(kāi)始逐個(gè)取休雌,更新所有進(jìn)程狀態(tài)
先走computeOomAdjLocked

根據(jù)進(jìn)程狀態(tài)來(lái)計(jì)算出對(duì)應(yīng)的adj和procState

前臺(tái)

  • 擁有當(dāng)前用戶可見(jiàn)的activity ,則adj=0肝断,procState=2
  • 擁有一個(gè)前臺(tái)service 杈曲,則adj=0驰凛,procState=4
  • 后臺(tái)進(jìn)程,且正在運(yùn)行receiver ,則adj=0担扑,procState=11
  • 后臺(tái)進(jìn)程,且正在運(yùn)行service 恰响,則adj=0,procState=10
  • 以上條件都不符合涌献,則adj=cachedAdj胚宦,procState=16

非前臺(tái)

  • 當(dāng)activity可見(jiàn), 則adj=1,procState=2燕垃;
  • 當(dāng)activity正在暫褪嗳埃或者已經(jīng)暫停, 則adj=2,procState=2卜壕;
  • 當(dāng)activity正在停止您旁, 則adj=2,procState=13(且activity尚未finish);
  • 以上都不滿足轴捎,否則procState=14

adj > 200的情況(可感知的后臺(tái)進(jìn)程)

  • 當(dāng)存在前臺(tái)service時(shí)鹤盒,則adj=2, procState=4;
  • 當(dāng)強(qiáng)制前臺(tái)時(shí)侦副,則adj=2, procState=6侦锯;

當(dāng)進(jìn)程為HeavyWeightProcess,則adj=4, procState=9跃洛;

當(dāng)進(jìn)程為HomeProcess情況率触,則adj=6, procState=12;

當(dāng)進(jìn)程為PreviousProcess情況汇竭,則adj=7, procState=13葱蝗;

備份進(jìn)程,則adj=3, procState=7或8

Service情況:

當(dāng)adj>0 或 schedGroup為后臺(tái)線程組 或procState>2時(shí)细燎,雙重循環(huán)遍歷:

  • 當(dāng)service已啟動(dòng)两曼,則procState<=10;
    • 當(dāng)service在30分鐘內(nèi)活動(dòng)過(guò)玻驻,則adj=5,cached=false;
  • 獲取service所綁定的connections
    • 當(dāng)client與當(dāng)前app同一個(gè)進(jìn)程悼凑,則continue;
    • 當(dāng)client進(jìn)程的ProcState >=cache,則設(shè)置為空進(jìn)程
    • 當(dāng)進(jìn)程存在顯示的ui璧瞬,則將當(dāng)前進(jìn)程的adj和ProcState值賦予給client進(jìn)程
    • 當(dāng)不存在顯示的ui户辫,且service上次活動(dòng)時(shí)間距離現(xiàn)在超過(guò)30分鐘,則只將當(dāng)前進(jìn)程的adj值賦予給client進(jìn)程
    • 當(dāng)前進(jìn)程adj > client進(jìn)程adj的情況
      • 當(dāng)service進(jìn)程比較重要時(shí)嗤锉,則設(shè)置adj >= -11
      • 當(dāng)client進(jìn)程adj<2,且當(dāng)前進(jìn)程adj>2時(shí)渔欢,則設(shè)置adj=2;
      • 當(dāng)client進(jìn)程adj>1時(shí),則設(shè)置adj = clientAdj
      • 否則瘟忱,設(shè)置adj <= 1奥额;
      • 若client進(jìn)程不是cache進(jìn)程苫幢,則當(dāng)前進(jìn)程也設(shè)置為非cache進(jìn)程
    • 當(dāng)綁定的是前臺(tái)進(jìn)程的情況
      • 當(dāng)client進(jìn)程狀態(tài)為前臺(tái)時(shí),則設(shè)置mayBeTop=true垫挨,并設(shè)置client進(jìn)程procState=16
      • 當(dāng)client進(jìn)程狀態(tài) < 2的前提下:若綁定前臺(tái)service韩肝,則clientProcState=3;否則clientProcState=6
    • 當(dāng)connections并沒(méi)有綁定前臺(tái)service時(shí)九榔,則clientProcState >= 7
    • 保證當(dāng)前進(jìn)程procState不會(huì)必client進(jìn)程的procState大
  • 當(dāng)進(jìn)程adj >0哀峻,且activity可見(jiàn) 或者resumed 或 正在暫停,則設(shè)置adj = 0

ContentProvider情況

當(dāng)adj>0 或 schedGroup為后臺(tái)線程組 或procState>2時(shí)帚屉,雙重循環(huán)遍歷:

  • 當(dāng)client與當(dāng)前app同一個(gè)進(jìn)程谜诫,則continue;
  • 當(dāng)client進(jìn)程procState >=14,則設(shè)置成procState =16
  • 沒(méi)有ui展示攻旦,則保證adj >=0
  • 當(dāng)client進(jìn)程狀態(tài)為前臺(tái)時(shí)喻旷,則設(shè)置mayBeTop=true,并設(shè)置client進(jìn)程procState=16設(shè)置為空進(jìn)程
  • 當(dāng)client進(jìn)程狀態(tài) < 2時(shí)牢屋,則clientProcState=3且预;
  • procState 比client進(jìn)程值更大時(shí),則取client端的狀態(tài)值烙无。
  • 當(dāng)contentprovider存在外部進(jìn)程依賴(非framework)時(shí)锋谐,則設(shè)置adj =0, procState=6

之后再根據(jù)一些邏輯調(diào)整下adj:d
比如:當(dāng)A類Service個(gè)數(shù) > service/3時(shí),則加入到B類Service

經(jīng)過(guò)computeOomAdjLocked之后,還存在部分進(jìn)程仍然未分配adj截酷,但是procState是有的涮拗。一般剩下的進(jìn)程只會(huì)被分配成cache和empty。

那么接下來(lái)再講講updateOomAdjLocked之后的進(jìn)程管理策略:

  • 當(dāng)cached進(jìn)程超過(guò)上限(cachedProcessLimit)迂苛,則殺掉該進(jìn)程
  • 當(dāng)空進(jìn)程超過(guò)上限(emptyProcessLimit)三热,則殺掉該進(jìn)程
  • 當(dāng)空進(jìn)程超過(guò)上限(TRIM_EMPTY_APPS為cachedProcessLimit的一半),且空閑時(shí)間超過(guò)30分鐘三幻,則殺掉該進(jìn)程

applyOomAdjLocked(app, true, now, nowElapsed);//應(yīng)用當(dāng)前進(jìn)程設(shè)置的adj

這部分其實(shí)就是把a(bǔ)dj把a(bǔ)dj值 通過(guò)socket通信發(fā)送給lmkd守護(hù)進(jìn)程就漾,并把對(duì)應(yīng)值寫入:/proc/<pid>/oom_score_adj

最后就是lowmemorykiller的查殺進(jìn)程邏輯了。具體可以參考我之前的文章:lowmemorykiller總結(jié)

}

四念搬、進(jìn)程管理的思考

站在系統(tǒng)的角度:

盡量權(quán)衡好內(nèi)存和用戶體驗(yàn)兩者關(guān)系

  • 對(duì)于內(nèi)存較大的手機(jī)抑堡,可以盡量多保證后臺(tái)進(jìn)程的數(shù)量,這樣可以保證APP啟動(dòng)速度
  • 對(duì)于內(nèi)存較小手機(jī)朗徊,減少cache/empty 進(jìn)程數(shù)量首妖,在一定情況下BServices進(jìn)程可以降級(jí)為cache/empty,利于殺死更多進(jìn)程爷恳。啟動(dòng)某些大應(yīng)用的時(shí)候悯搔,可以把cache/empty清理掉,比如啟動(dòng)相機(jī)、啟動(dòng)某款大型游戲等等妒貌。
  • 對(duì)于一些熱門的APP做白名單來(lái)給特權(quán),保障使用體驗(yàn)等等铸豁。

站在應(yīng)用的角度:

肯定是希望自己能存活越久越好灌曙,這就牽扯到一些進(jìn)程保活的方式(這個(gè)后續(xù)會(huì)總結(jié))节芥,其中一類就是想辦法提高進(jìn)程的adj在刺,但是凡是不是以真正業(yè)務(wù)需要來(lái)強(qiáng)行保活的行為都是耍流氓头镊。

五蚣驼、對(duì)APP開(kāi)發(fā)者的建議
  1. 只有真正需要用戶可感知的應(yīng)用,才調(diào)用startForegroundService()方法來(lái)啟動(dòng)前臺(tái)服務(wù)相艇,此時(shí)ADJ=PERCEPTIBLE_APP_ADJ(200)颖杏,常駐內(nèi)存,并且會(huì)在通知欄常駐通知提醒用戶坛芽,比如音樂(lè)播放留储,地圖導(dǎo)航。切勿為了常駐而濫用前臺(tái)服務(wù)咙轩,這會(huì)嚴(yán)重影響用戶體驗(yàn)获讳。

  2. 進(jìn)程中的Service工作完成后,務(wù)必主動(dòng)調(diào)用stopService或stopSelf來(lái)停止服務(wù)活喊,避免占據(jù)內(nèi)存丐膝,浪費(fèi)系統(tǒng)資源;

  3. 不要長(zhǎng)時(shí)間綁定其他進(jìn)程的service或者provider钾菊,每次使用完成后應(yīng)立刻釋放帅矗,避免其他進(jìn)程常駐于內(nèi)存;

  4. APP應(yīng)該實(shí)現(xiàn)接口onTrimMemory()和onLowMemory()结缚,根據(jù)TrimLevel適當(dāng)?shù)貙⒎潜仨殐?nèi)存在回調(diào)方法中加以釋放损晤。當(dāng)系統(tǒng)內(nèi)存緊張時(shí)會(huì)回調(diào)該接口,減少系統(tǒng)卡頓與殺進(jìn)程頻次红竭。

  5. 減少在庇妊活上花心思,更應(yīng)該在優(yōu)化內(nèi)存上下功夫茵宪,因?yàn)樵谙嗤珹DJ級(jí)別的情況下最冰,系統(tǒng)會(huì)選擇優(yōu)先殺內(nèi)存占用大的進(jìn)程。

六稀火、一個(gè)小Tips

UI進(jìn)程與Service進(jìn)程一定要分離暖哨,因?yàn)閷?duì)于包含activity的service進(jìn)程,一旦進(jìn)入后臺(tái)就有機(jī)會(huì)成為cache進(jìn)程(ADJ>=900)凰狞,隨時(shí)可能會(huì)被系統(tǒng)回收篇裁;而分離后的Service進(jìn)程服務(wù)屬于SERVICE_ADJ(500)沛慢,被殺的可能性相對(duì)較小。尤其是系統(tǒng)允許自啟動(dòng)的服務(wù)進(jìn)程必須做UI分離达布,避免消耗系統(tǒng)較大內(nèi)存团甲。

if (app.hasShownUi && app != mHomeProcess) {
    // If this process has shown some UI, let it immediately
    // go to the LRU list because it may be pretty heavy with
    // UI stuff.  We'll tag it with a label just to help
    // debug and understand what is going on.
    if (adj > ProcessList.SERVICE_ADJ) {
        app.adjType = "cch-started-ui-services";
    }

修改方案:
1當(dāng)前進(jìn)程不運(yùn)行Activity, 只運(yùn)行Service
2 采用fg-service

參考:
http://gityuan.com/2018/05/19/android-process-adj/

系列文章:
Android進(jìn)程管理篇(一)-應(yīng)用進(jìn)程啟動(dòng)過(guò)程
Android進(jìn)程管理篇(二)-進(jìn)程查殺方式總結(jié)
Android進(jìn)程管理篇(三)-AMS進(jìn)程調(diào)度
lowmemorykiller總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者黍聂。
  • 序言:七十年代末躺苦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子产还,更是在濱河造成了極大的恐慌匹厘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脐区,死亡現(xiàn)場(chǎng)離奇詭異愈诚,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)坡椒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門扰路,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人倔叼,你說(shuō)我怎么就攤上這事汗唱。” “怎么了丈攒?”我有些...
    開(kāi)封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵哩罪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我巡验,道長(zhǎng)际插,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任显设,我火速辦了婚禮框弛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捕捂。我一直安慰自己瑟枫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布指攒。 她就那樣靜靜地躺著慷妙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪允悦。 梳的紋絲不亂的頭發(fā)上膝擂,一...
    開(kāi)封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼架馋。 笑死狞山,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叉寂。 我是一名探鬼主播铣墨,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼办绝!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起姚淆,我...
    開(kāi)封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤孕蝉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后腌逢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體降淮,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年搏讶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了佳鳖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡媒惕,死狀恐怖系吩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妒蔚,我是刑警寧澤穿挨,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站肴盏,受9級(jí)特大地震影響科盛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜菜皂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一贞绵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恍飘,春花似錦榨崩、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至胳施,卻和暖如春溯祸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工焦辅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留博杖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓筷登,卻偏偏與公主長(zhǎng)得像剃根,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子前方,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355