導航:首頁 > 操作系統 > android線程調度

android線程調度

發布時間:2023-09-07 11:56:01

❶ 每個android 都應必須了解的多線程知識點~

進程是系統調度和資源分配的一個獨立單位。

在Android中,一個應用程序就是一個獨立的集成,應用運行在一個獨立的環境中,可以避免其他應用程序/進程的干擾。當我們啟動一個應用程序時,系統就會創建一個進程(該進程是從Zygote中fork出來的,有獨立的ID),接著為這個進程創建一個主線程,然後就可以運行MainActivity了,應用程序的組件默認都是運行在其進程中。開發者可以通過設置應用的組件的運行進程,在清單文件中給組件設置:android:process = "進程名";可以達到讓組件運行在不同進程中的目的。讓組件運行在不同的進程中,既有好處,也有壞處。我們依次的說明下。

好處:每一個應用程序(也就是每一個進程)都會有一個內存預算,所有運行在這個進程中的程序使用的總內存不能超過這個值,讓組件運行不同的進程中,可以讓主進程可以擁有更多的空間資源。當我們的應用程序比較大,需要的內存資源比較多時(也就是用戶會抱怨應用經常出現OutOfMemory時),可以考慮使用多進程。

壞處:每個進程都會有自己的虛擬機實例,因此讓在進程間共享一些數據變得相對困難,需要採用進程間的通信來實現數據的共享。

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。

在Android中,線程會有那麼幾種狀態:創建、就緒、運行、阻塞、結束。當應用程序有組件在運行時,UI線程是處於運行狀態的。默認情況下,應用的所有組件的操作都是在UI線程里完成的,包括響應用戶的操作(觸摸,點擊等),組件生命周期方法的調用,UI的更新等。因此如果UI線程處理阻塞狀態時(在線程里做一些耗時的操作,如網路連接等),就會不能響應各種操作,如果阻塞時間達到5秒,就會讓程序處於ANR(application not response)狀態。

1.線程作用

減少程序在並發執行時所付出的時空開銷,提高操作系統的並發性能。

2.線程分類

守護線程、非守護線程(用戶線程)

2.1 守護線程

定義:守護用戶線程的線程,即在程序運行時為其他線程提供一種通用服務
常見:如垃圾回收線程
設置方式:thread.setDaemon(true);//設置該線程為守護線程

2.2 非守護線程(用戶線程)

主線程 & 子線程。

2.2.1 主線程(UI線程)

定義:Android系統在程序啟動時會自動啟動一條主線程
作用:處理四大組件與用戶進行交互的事情(如UI、界面交互相關)
因為用戶隨時會與界面發生交互,因此主線程任何時候都必須保持很高的響應速度,所以主線程不允許進行耗時操作,否則會出現ANR。

2.2.2 子線程(工作線程)

定義:手動創建的線程
作用:耗時的操作(網路請求、I/O操作等)

2.3 守護線程與非守護線程的區別和聯系

區別:虛擬機是否已退出,即
a. 當所有用戶線程結束時,因為沒有守護的必要,所以守護線程也會終止,虛擬機也同樣退出
b. 反過來,只要任何用戶線程還在運行,守護線程就不會終止,虛擬機就不會退出

3.線程優先順序

3.1 表示

線程優先順序分為10個級別,分別用Thread類常量表示。

3.2 設置

通過方法setPriority(int grade)進行優先順序設置,默認線程優先順序是5,即 Thread.NORM_PRIORITY。

4.線程狀態

創建狀態:當用 new 操作符創建一個線程的時候

就緒狀態:調用 start 方法,處於就緒狀態的線程並不一定馬上就會執行 run 方法,還需要等待CPU的調度

運行狀態:CPU 開始調度線程,並開始執行 run 方法

阻塞(掛起)狀態:線程的執行過程中由於一些原因進入阻塞狀態,比如:調用 sleep/wait 方法、嘗試去得到一個鎖等

結束(消亡)狀態:run 方法執行完 或者 執行過程中遇到了一個異常

(1)start()和run()的區別

通過調用Thread類的start()方法來啟動一個線程,這時此線程是處於就緒狀態,並沒有運行。調用Thread類調用run()方法來完成其運行操作的,方法run()稱為線程體,它包含了要執行的這個線程的內容,run()運行結束,此線程終止,然後CPU再調度其它線程。

(2)sleep()、wait()、yield()的區別

sleep()方法屬於Thread類,wait()方法屬於Object類。
調用sleep()方法,線程不會釋放對象鎖,只是暫停執行指定的時間,會自動恢復運行狀態;調用wait()方法,線程會放棄對象鎖,進入等待此對象的等待鎖定池,不調用notify()方法,線程永遠處於就緒(掛起)狀態。

yield()直接由運行狀態跳回就緒狀態,表示退讓線程,讓出CPU,讓CPU調度器重新調度。禮讓可能成功,也可能不成功,也就是說,回到調度器和其他線程進行公平競爭。

1.Android線程的原則

(1)為什麼不能再主線程中做耗時操作
防止ANR, 不能在UI主線程中做耗時的操作,因此我們可以把耗時的操作放在另一個工作線程中去做。操作完成後,再通知UI主線程做出相應的響應。這就需要掌握線程間通信的方式了。 在Android中提供了兩種線程間的通信方式:一種是AsyncTask機制,另一種是Handler機制。

(2)為什麼不能在非UI線程中更新UI 因為Android的UI線程是非線程安全的,應用更新UI,是調用invalidate()方法來實現界面的重繪,而invalidate()方法是非線程安全的,也就是說當我們在非UI線程來更新UI時,可能會有其他的線程或UI線程也在更新UI,這就會導致界面更新的不同步。因此我們不能在非UI主線程中做更新UI的操作。

2.Android實現多線程的幾種方式

3.為何需要多線程

多線程的本質就是非同步處理,直觀一點說就是不要讓用戶感覺到「很卡」。

4.多線程機制的核心是啥

多線程核心機制是Handler

推薦Handler講解視頻: 面試總被問到Handler?帶你從源碼的角度解讀Handler核心機制

根據上方提到的 多進程、多線程、Handler 問題,我整理了一套 Binder與Handler 機制解析的學習文檔,提供給大家進行學習參考,有需要的可以 點擊這里直接獲取!!! 裡面記錄許多Android 相關學習知識點。

❷ android多核,多線程該如何用

在程序開發的實踐當中,為了讓程序表現得更加流暢,我們肯定會需要使用到多線程來提升程序的並發執行性能。但是編寫多線程並發的代碼一直以來都是一個相對棘手的問題,所以想要獲得更佳的程序性能,我們非常有必要掌握多線程並發編程的基礎技能。
眾所周知,Android 程序的大多數代碼操作都必須執行在主線程,例如系統事件(例如設備屏幕發生旋轉),輸入事件(例如用戶點擊滑動等),程序回調服務,UI 繪制以及鬧鍾事件等等。那麼我們在上述事件或者方法中插入的代碼也將執行在主線程。

一旦我們在主線程裡面添加了操作復雜的代碼,這些代碼就很可能阻礙主線程去響應點擊/滑動事件,阻礙主線程的 UI 繪制等等。我們知道,為了讓屏幕的刷新幀率達到 60fps,我們需要確保 16ms 內完成單次刷新的操作。一旦我們在主線程裡面執行的任務過於繁重就可能導致接收到刷新信號的時候因為資源被佔用而無法完成這次刷新操作,這樣就會產生掉幀的現象,刷新幀率自然也就跟著下降了(一旦刷新幀率降到 20fps 左右,用戶就可以明顯感知到卡頓不流暢了)。

為了避免上面提到的掉幀問題,我們需要使用多線程的技術方案,把那些操作復雜的任務移動到其他線程當中執行,這樣就不容易阻塞主線程的操作,也就減小了出現掉幀的可能性。

那麼問題來了,為主線程減輕負的多線程方案有哪些呢?這些方案分別適合在什麼場景下使用?Android 系統為我們提供了若干組工具類來幫助解決這個問題。
AsyncTask: 為 UI 線程與工作線程之間進行快速的切換提供一種簡單便捷的機制。適用於當下立即需要啟動,但是非同步執行的生命周期短暫的使用場景。
HandlerThread: 為某些回調方法或者等待某些任務的執行設置一個專屬的線程,並提供線程任務的調度機制。
ThreadPool: 把任務分解成不同的單元,分發到各個不同的線程上,進行同時並發處理。
IntentService: 適合於執行由 UI 觸發的後台 Service 任務,並可以把後台任務執行的情況通過一定的機制反饋給 UI。
了解這些系統提供的多線程工具類分別適合在什麼場景下,可以幫助我們選擇合適的解決方案,避免出現不可預期的麻煩。雖然使用多線程可以提高程序的並發量,但是我們需要特別注意因為引入多線程而可能伴隨而來的內存問題。舉個例子,在 Activity 內部定義的一個 AsyncTask,它屬於一個內部類,該類本身和外面的 Activity 是有引用關系的,如果 Activity 要銷毀的時候,AsyncTask 還仍然在運行,這會導致 Activity 沒有辦法完全釋放,從而引發內存泄漏。所以說,多線程是提升程序性能的有效手段之一,但是使用多線程卻需要十分謹慎小心,如果不了解背後的執行機制以及使用的注意事項,很可能引起嚴重的問題。

❸ Android中的線程狀態 - AsyncTask詳解

在操作系統中,線程是操作系統調度的最小單元,同時線程又是一種受限的系統資源,即線程不可能無限制地產生,並且 線程的創建和銷毀都會有相應的開銷。 當系統中存在大量的線程時,系統會通過會時間片輪轉的方式調度每個線程,因此線程不可能做到絕對的並行。

如果在一個進程中頻繁地創建和銷毀線程,顯然不是高效的做法。正確的做法是採用線程池,一個線程池中會緩存一定數量的線程,通過線程池就可以避免因為頻繁創建和銷毀線程所帶來的系統開銷。

AsyncTask是一個抽象類,它是由Android封裝的一個輕量級非同步類(輕量體現在使用方便、代碼簡潔),它可以在線程池中執行後台任務,然後把執行的進度和最終結果傳遞給主線程並在主線程中更新UI。

AsyncTask的內部封裝了 兩個線程池 (SerialExecutor和THREAD_POOL_EXECUTOR)和 一個Handler (InternalHandler)。

其中 SerialExecutor線程池用於任務的排隊,讓需要執行的多個耗時任務,按順序排列 THREAD_POOL_EXECUTOR線程池才真正地執行任務 InternalHandler用於從工作線程切換到主線程

1.AsyncTask的泛型參數

AsyncTask是一個抽象泛型類。

其中,三個泛型類型參數的含義如下:

Params: 開始非同步任務執行時傳入的參數類型;

Progress: 非同步任務執行過程中,返回下載進度值的類型;

Result: 非同步任務執行完成後,返回的結果類型;

如果AsyncTask確定不需要傳遞具體參數,那麼這三個泛型參數可以用Void來代替。

有了這三個參數類型之後,也就控制了這個AsyncTask子類各個階段的返回類型,如果有不同業務,我們就需要再另寫一個AsyncTask的子類進行處理。

2.AsyncTask的核心方法

onPreExecute()

這個方法會在 後台任務開始執行之間調用,在主線程執行。 用於進行一些界面上的初始化操作,比如顯示一個進度條對話框等。

doInBackground(Params...)

這個方法中的所有代碼都會 在子線程中運行,我們應該在這里去處理所有的耗時任務。

任務一旦完成就可以通過return語句來將任務的執行結果進行返回,如果AsyncTask的第三個泛型參數指定的是Void,就可以不返回任務執行結果。 注意,在這個方法中是不可以進行UI操作的,如果需要更新UI元素,比如說反饋當前任務的執行進度,可以調用publishProgress(Progress...)方法來完成。

onProgressUpdate(Progress...)

當在後台任務中調用了publishProgress(Progress...)方法後,這個方法就很快會被調用,方法中攜帶的參數就是在後台任務中傳遞過來的。 在這個方法中可以對UI進行操作,在主線程中進行,利用參數中的數值就可以對界面元素進行相應的更新。

onPostExecute(Result)

當doInBackground(Params...)執行完畢並通過return語句進行返回時,這個方法就很快會被調用。返回的數據會作為參數傳遞到此方法中, 可以利用返回的數據來進行一些UI操作,在主線程中進行,比如說提醒任務執行的結果,以及關閉掉進度條對話框等。

上面幾個方法的調用順序:

onPreExecute() --> doInBackground() --> publishProgress() --> onProgressUpdate() --> onPostExecute()

如果不需要執行更新進度則為onPreExecute() --> doInBackground() --> onPostExecute(),

除了上面四個方法,AsyncTask還提供了onCancelled()方法, 它同樣在主線程中執行,當非同步任務取消時,onCancelled()會被調用,這個時候onPostExecute()則不會被調用 ,但是要注意的是, AsyncTask中的cancel()方法並不是真正去取消任務,只是設置這個任務為取消狀態,我們需要在doInBackground()判斷終止任務。就好比想要終止一個線程,調用interrupt()方法,只是進行標記為中斷,需要在線程內部進行標記判斷然後中斷線程。

3.AsyncTask的簡單使用

這里我們模擬了一個下載任務,在doInBackground()方法中去執行具體的下載邏輯,在onProgressUpdate()方法中顯示當前的下載進度,在onPostExecute()方法中來提示任務的執行結果。如果想要啟動這個任務,只需要簡單地調用以下代碼即可:

4.使用AsyncTask的注意事項

①非同步任務的實例必須在UI線程中創建,即AsyncTask對象必須在UI線程中創建。

②execute(Params... params)方法必須在UI線程中調用。

③不要手動調用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)這幾個方法。

④不能在doInBackground(Params... params)中更改UI組件的信息。

⑤一個任務實例只能執行一次,如果執行第二次將會拋出異常。

先從初始化一個AsyncTask時,調用的構造函數開始分析。

這段代碼雖然看起來有點長,但實際上並沒有任何具體的邏輯會得到執行,只是初始化了兩個變數,mWorker和mFuture,並在初始化mFuture的時候將mWorker作為參數傳入。mWorker是一個Callable對象,mFuture是一個FutureTask對象,這兩個變數會暫時保存在內存中,稍後才會用到它們。 FutureTask實現了Runnable介面,關於這部分內容可以看這篇文章。

mWorker中的call()方法執行了耗時操作,即result = doInBackground(mParams);,然後把執行得到的結果通過postResult(result);,傳遞給內部的Handler跳轉到主線程中。在這里這是實例化了兩個變數,並沒有開啟執行任務。

那麼mFuture對象是怎麼載入到線程池中,進行執行的呢?

接著如果想要啟動某一個任務,就需要調用該任務的execute()方法,因此現在我們來看一看execute()方法的源碼,如下所示:

調用了executeOnExecutor()方法,具體執行邏輯在這個方法裡面:

可以 看出,先執行了onPreExecute()方法,然後具體執行耗時任務是在exec.execute(mFuture),把構造函數中實例化的mFuture傳遞進去了。

exec具體是什麼?

從上面可以看出具體是sDefaultExecutor,再追溯看到是SerialExecutor類,具體源碼如下:

終於追溯到了調用了SerialExecutor 類的execute方法。SerialExecutor 是個靜態內部類,是所有實例化的AsyncTask對象公有的,SerialExecutor 內部維持了一個隊列,通過鎖使得該隊列保證AsyncTask中的任務是串列執行的,即多個任務需要一個個加到該隊列中,然後執行完隊列頭部的再執行下一個,以此類推。

在這個方法中,有兩個主要步驟。

①向隊列中加入一個新的任務,即之前實例化後的mFuture對象。

②調用 scheleNext()方法,調用THREAD_POOL_EXECUTOR執行隊列頭部的任務。

由此可見SerialExecutor 類僅僅為了保持任務執行是串列的,實際執行交給了THREAD_POOL_EXECUTOR。

THREAD_POOL_EXECUTOR又是什麼?

實際是個線程池,開啟了一定數量的核心線程和工作線程。然後調用線程池的execute()方法。執行具體的耗時任務,即開頭構造函數中mWorker中call()方法的內容。先執行完doInBackground()方法,又執行postResult()方法,下面看該方法的具體內容:

該方法向Handler對象發送了一個消息,下面具體看AsyncTask中實例化的Hanlder對象的源碼:

在InternalHandler 中,如果收到的消息是MESSAGE_POST_RESULT,即執行完了doInBackground()方法並傳遞結果,那麼就調用finish()方法。

如果任務已經取消了,回調onCancelled()方法,否則回調 onPostExecute()方法。

如果收到的消息是MESSAGE_POST_PROGRESS,回調onProgressUpdate()方法,更新進度。

InternalHandler是一個靜態類,為了能夠將執行環境切換到主線程,因此這個類必須在主線程中進行載入。所以變相要求AsyncTask的類必須在主線程中進行載入。

到此為止,從任務執行的開始到結束都從源碼分析完了。

AsyncTask的串列和並行

從上述源碼分析中分析得到,默認情況下AsyncTask的執行效果是串列的,因為有了SerialExecutor類來維持保證隊列的串列。如果想使用並行執行任務,那麼可以直接跳過SerialExecutor類,使用executeOnExecutor()來執行任務。

四、AsyncTask使用不當的後果

1.)生命周期

AsyncTask不與任何組件綁定生命周期,所以在Activity/或者Fragment中創建執行AsyncTask時,最好在Activity/Fragment的onDestory()調用 cancel(boolean);

2.)內存泄漏

3.) 結果丟失

屏幕旋轉或Activity在後台被系統殺掉等情況會導致Activity的重新創建,之前運行的AsyncTask(非靜態的內部類)會持有一個之前Activity的引用,這個引用已經無效,這時調用onPostExecute()再去更新界面將不再生效。

自己是從事了七年開發的Android工程師,不少人私下問我,2019年Android進階該怎麼學,方法有沒有?

沒錯,年初我花了一個多月的時間整理出來的學習資料,希望能幫助那些想進階提升Android開發,卻又不知道怎麼進階學習的朋友。【 包括高級UI、性能優化、架構師課程、NDK、Kotlin、混合式開發(ReactNative+Weex)、Flutter等架構技術資料 】,希望能幫助到您面試前的復習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習。

❹ Android線程池的使用

在Android中有主線程和子線程的區分。主線程又稱為UI線程,主要是處理一些和界面相關的事情,而子線程主要是用於處理一些耗時比較大的一些任務,例如一些網路操作,IO請求等。如果在主線程中處理這些耗時的任務,則有可能會出現ANR現象(App直接卡死)。

線程池,從名字的表明含義上我們知道線程池就是包含線程的一個池子,它起到新建線程、管理線程、調度線程等作用。

既然Android中已經有了線程的概念,那麼為什麼需要使用線程池呢?我們從兩個方面給出使用線程池的原因。

在Android中線程池就是ThreadPoolExecutor對象。我們先來看一下ThreadPoolExecutor的構造函數。

我們分別說一下當前的幾個參數的含義:
第一個參數corePoolSize為 核心線程數 ,也就是說線程池中至少有這么多的線程,即使存在的這些線程沒有執行任務。但是有一個例外就是,如果在線程池中設置了allowCoreThreadTimeOut為true,那麼在 超時時間(keepAliveTime) 到達後核心線程也會被銷毀。
第二個參數maximumPoolSize為 線程池中的最大線程數 。當活動線程數達到這個數後,後續添加的新任務會被阻塞。
第三個參數keepAliveTime為 線程的保活時間 ,就是說如果線程池中有多於核心線程數的線程,那麼在線程沒有任務的那一刻起開始計時,如果超過了keepAliveTime,還沒有新的任務過來,則該線程就要被銷毀。同時如果設置了allowCoreThreadTimeOut為true,該時間也就是上面第一條所說的 超時時間
第四個參數unit為 第三個參數的計時單位 ,有毫秒、秒等。
第五個參數workQueue為 線程池中的任務隊列 ,該隊列持有由execute方法傳遞過來的Runnable對象(Runnable對象就是一個任務)。這個任務隊列的類型是BlockQueue類型,也就是阻塞隊列,當隊列的任務數為0時,取任務的操作會被阻塞;當隊列的任務數滿了(活動線程達到了最大線程數),添加操作就會阻塞。
第六個參數threadFactory為 線程工廠 ,當線程池需要創建一個新線程時,使用線程工廠來給線程池提供一個線程。
第七個參數handler為 拒絕策略 ,當線程池使用有界隊列時(也就是第五個參數),如果隊列滿了,任務添加到線程池的時候的一個拒絕策略。

可以看到FixedThreadPool的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出FixedThreadPool的幾個特點:

可以看到CacheThreadPool的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出CacheThreadPool的幾個特點:

可以看到ScheledThreadPoolExecutor的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出ScheledThreadPoolExecutor的幾個特點:

可以看到SingleThreadExecutor的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出SingleThreadExecutor的幾個特點:

❺ Android進程與線程區別

所以下來特地去查了以下資料,先說說線程:
(1)在Android APP中,只允許有一個主線程,進行UI的渲染等等,但是不能進行耗時操作(網路交互等等),否則會造成ANR,就是線程阻塞卡死,未響應。
(2)除了主線程之外,耗時操作都應該規范到子線程中,線程之間會有相應的通信方式,但相互獨立。
(3)然後看了一下所查資料:
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程比進程更小,基本上不擁有系統資源,故對它的調度所用資源小,能更高效的提高系統內多個程序間並發執行的。 嗯,從大的說就是這樣。
在平時的Android開發過程中,基本上都會用到線程handler,thread等等,具體的實現方法我就不在這里寫了。

進程:
根據所查資料:是一個具有獨立功能的程序關於某個數據集合的一次運行活動。進程是系統進行資源分配和調度的一個獨立單位。可以申請和擁有系統資源,是一個動態的概念,是一個活動的實體,是一個「執行中的程序」。不只是程序的代碼,還包括當前的活動。
這應該是一個比較大的概念,存在於一個系統中,與線程的區別是:

1、子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器為其執行上下文。
2、進程間相互獨立,同一進程的各線程間共享。某進程內的線程在其它進程不可見。

3、進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變數)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。

4、線程上下文切換比進程上下文切換要快得多。

❻ android開發中線程有幾種狀態,分別是哪些

【答案】:1)、新建狀態(New):新創建了一個線程對象。
2)、就緒狀態(Runnable):線程對象創建後,前螞消其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3)、運行狀態(Running):就緒狀態的線程獲取了CPU,執行run()方法。
4)、阻塞狀態(Blocked):阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。阻塞的情況分三種:
(一)、等待阻塞慧知:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖物卜池中。
(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
5)、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
當調用start方法的時候,該線程就進入就緒狀態。等待CPU進行調度執行,此時還沒有真正執行線程。
當調用run方法的時候,是已經被CPU進行調度,執行線程的主要任務。

閱讀全文

與android線程調度相關的資料

熱點內容
壓縮機工藝管是多大的 瀏覽:310
安卓刷什麼系統穩定 瀏覽:33
程序員寫炫酷代碼 瀏覽:928
大話存儲pdf 瀏覽:524
中銘機器人怎麼編程 瀏覽:812
把字母變為數字的加密法 瀏覽:523
噬血狂襲第三季哪個app能看 瀏覽:421
江蘇螺桿壓縮機 瀏覽:980
android底部彈出對話框 瀏覽:501
怎麼查伺服器同行fc號 瀏覽:999
什麼伺服器雲鳥最便宜 瀏覽:220
vs編譯器反匯編 瀏覽:570
程序員直播做項目創業 瀏覽:403
linux下samba配置 瀏覽:797
程序員面試銀行崗位會有編制嗎 瀏覽:414
ex表怎麼加密碼保護 瀏覽:173
小孩上編程課用哪款好 瀏覽:559
如何製作伺服器商店 瀏覽:736
壓縮氣管閥門 瀏覽:466
pdf推文 瀏覽:361