① android里有哪些方法啟動線程
其實Android啟動線程和java一樣有兩種方式,一種是直接Thread類的start方法,也就是一般寫一個自己的類來繼承Thread類。另外一種方式其實和這個差不多啊! 那就是Runnable介面,然後把Runnable的子類對象傳遞給Thread類再創建Thread對象.總之都是需要創建Thread對象,然後調用Thread類的start方法啟動線程。區別就是,一個是直接創建Thread對象,另外一個是需要implement了Runnable介面對象作為創建Thread對象的參數。Runnable其實我們稱為線程任務。
第一種方式一般是這樣用:
Class MyThread extends Thread{
public void run(){
//你要實現的代碼
}
}
在主線程中啟動這個線程:
public class Test{
public static void main(String[] args){
new MyThread().start();//啟動了我們的線程了
}
}
2,第二種方式一般是這樣用:
public class MyRunnable implements Runnable{
public void run(){
//你需要實現的代碼
}
}
在主線程中啟動這個線程:
public class Test{
public static void main(String[] args){
Thread t=new Thread(new MyRunnable());//這里比第一種創建線程對象多了個任務對象
t.start();
}
}
這里我想說的是可能你問這個問題是接觸到了Android中的Handler概念:
其實Handler並不是開辟新線程的概念,Android主要的考慮到更新界面的問題,一般情況下,更新界面(Activity)都是在主線程中更新的,這樣就遇到了一個問題,比方說:在下載文件時候我們需要進度條顯示下載進度,界面需要更新(數據是不斷變的,也就是下載的大小是不斷變的,要是直接在主線程中更新,就會造成程序的堵塞,程序很容易崩潰,通常這樣聯網耗時的工作需要開辟另外一個線程的,這樣就不會影響主程序了),好了,到這里聯網操作一般都需要開辟新線程了吧。。
接下來就來說Handler了,剛剛我說了Handler不是開辟新線程,在我看來,Handler更像是主線程的秘書,是一個觸發器,負責管理從子線程中得到更新的數據,然後在主線程中更新界面。簡單說下進度條的那個:
下載了多少的數據都是在子線程中得到的,在子線程中通過Handler的sendMessage()方法發送得到的下載的數據,當你調用了sendMessage方法後,Handler就會回調(也就是自動調用)Handler中的 HandlerMessage方法。
我很認真寫了,希望分給我! 要是還有不懂的,可以追問,總之Handler不是開辟線程,開辟線程的方式就和JAVA一樣的! 千萬不要被Android中的Handler混淆。
② Android中的線程池
線程池的好處
1、重用線程池中的線程,避免線程的創建與銷毀帶來的性能開銷
2、能有效控制線程池的最大並發數,避免大量線程因搶占資源而導致的阻塞
3、能對線程進行簡單的管理,提供定時或者指定間隔時間、循環執行等操作
線程池的概率來自於java的Executor介面,實現類是ThreadPoolExecutor, 它提供一系列的參數來配置線程池,以此構建不同的線程池。Android的線程池分4類,都是通過Executors所提供的工廠方法來得到。
ThreadPoolExecutor有四個構造函數,下面這個是最常用的
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnnable> workQueue, ThreadFactory threadFactory)
corePoolSize
線程池中的核心線程數,默認情況下核心線程會在線程池中一直存活,即使他們處於閑置狀態。如果設置ThreadPoolExecutor 中的allowCoreThreadTimeOut = true, 核心線程在等待新任務到來時有超時機制,時間超過keepAliveTime所指定的時間後,核心線程會終止。
maximumPoolSize
最大線程數
keepAliveTime
非核心線程閑置的超時時間,超過這個時間,非核心線程會被回收。核心線程則要看allowCoreThreadTimeOut屬性的值。
unit
時間單位
workQueue
線程池中的工作隊列
threadFactory
線程工廠,為線程池提供創建新線程的功能。
舉個例子,我們常用的okhttp內部也是使用了線程池,它的ThreadPoolExecutor主要是定義在Dispatcher類裡面。 使用的是CachedThreadPool。
executorService = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS, SynchronousQueue(), ThreadFactory("okhttp Dispatcher", false))
1、FixedThreadPool
通過Executors的newFixedThreadPool()創建,這是一個線程數量固定的線程池,裡面所有的線程都是核心線程。
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
}
2、CachedThreadPool
通過Executors的newCacheThreadPool()創建,這是一個線程數量不定的線程池,裡面所有的線程都是非核心線程。最大線程數是無限大,當線程池中的線程都處於活動狀態時,新的task會創建新的線程來處理,否則就使用空閑的線程處理,所有的線程都是60s的超時時間,超時後會自動回收。
public static ExecutorService newFixedThreadPool(){
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>())
}
3、ScheledThreadPool
通過Executors的newScheledThreadPool()創建, 核心線程固定,非核心線程無限大,當非核心線程空閑時,會立即被回收。適合做定時任務或者固定周期的重復任務。
public static ExecutorService newScheledThreadPool(int corePoolSize){
return new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.SECONDS, new DelayedWorkQueue())
}
4、SingleThreadExcecutor
通過Executors的newSingleThreadPool()創建,內部只有一個核心線程。
public static ExecutorService newFixedThreadPool(){
return new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
}
課外知識:LinkedBlockingQueue
LinkedBlockingQueue是由鏈表組成的阻塞隊列,內部head 指向隊列第一個元素,last指向最後一個元素。入隊和出隊都會加鎖阻塞,都是使用了不同的鎖。
DelayedWorkQueue
延時隊列,隊內元素必須是Delayed的實現類。對內元素會按照Delayed時間進行排序,對內元素只有在delayed時間過期了才能出隊。
入隊的時候不阻塞隊列,出隊的時候,如果隊列為空或者隊列里所有元素都等待時間都沒有到期,則該線程進入阻塞狀態。
③ 如何為android添加新的線程
new Thread(new Runnable(){
public void run(){
//TODO
//在這里寫要處理的操作,子線程中不能處理舉裂手UI的操作(如:源談textView.setText("cc");),否則報錯
}
}
).start();
這樣就開了新的線程了。
線程可以結合Handler來使用,需要獲取線程內部的消息,可正嫌以使用Handler將消息發送到UI主線程中。
④ android開發中,如何在做一些耗時的操作時,另起一個新線程
handler其實就是消息處理機制。首先在主線程也就是UI創建一個Handler對象,復寫其中的handMessage( Message msg)方法。該方法里的msg就是子線程發來的消息,表示子線程處理完了,以這個msg來通知主線程。讓主線程來作UI的繪制工作。
那麼子線程工作完了就要發消息了,比如:
run(){
data = getDataFromInternet();//耗時工作
Message msg = handler.obtainMessage(0, data);//通過handler得到消息,該消息的標識為0,消息內容是data
handler.sendMessage(msg);//發送
}
然後handler在主線程就負責接收:
public Handler handler = new Handler(){//處理UI繪制
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
data = (List<Map<String, Object>>) msg.obj;
if(data == null){
Toast.makeText(AllMovieActivity.this, "網路連接失敗,獲取不到影片信息", 1).show();
}else {
adapter = new HotMoviedapter(AllMovieActivity.this, data, R.layout.allmovielist_item,
new String[] { "picurl", "chname", "director", "leadrole",
"fshowtime", "country" }, new int[] { R.id.picurl,
R.id.chname, R.id.director, R.id.leadrole,
R.id.fshowtime, R.id.country },mListView);
TextView v = new TextView(AllMovieActivity.this);
v.setHeight(80);
v.setSelectAllOnFocus(false);
mListView.addFooterView(v);
mListView.setAdapter(adapter);
}
break;
default:
break;
}
}
};
⑤ android開發中,如何在做一些耗時的操作時,另起一個新線程20170819 13:21
1、第一種方式:使用Thread不帶參數的構造方法,並重寫run()方法<pre t="code" l="as3">new Thread(){
public void run(){
//在run方法中調用需要執行的代碼,完成後發送消息與主線程交互
Message msg=new Message();
msg.what=110;
handler.sengMessage();
}
}.start();2、第二種方式:使用Thread帶參數的構造方法,並重寫Runable()中的run方法<pre t="code" l="java">new Thread(new Runable(){
public void run(){
//在run方法中調用需要執行的代碼,完成後發送消息與主線程交互
Message msg=new Message();
msg.what=110;
handler.sengMessage();
}).start();3、在UI線程中接收Thread子線程發送的消息,刷新UI界面
⑥ 求教android在新線程中調用webview方法的最佳實踐
{
staticandroid.os.Handlerh=null;
staticWebVieww=null;
publicstaticvoidgetWebView(WebVieww0){//有點想不起來webview的類名是啥了,強答
w=w0;
h=newandroid.os.Handler();//請用UI線程來運行這段代碼
}
publicstaticvoiddoWithWebView(){
newThread(){//開新線程
@Overridepublicvoidrun(){
try{//裡面寫新線程執行內容
/*
XXX耗時內容爛神……
*/
大凳h.post(newRunnable(){//用handler轉交UI處理操作
@Overridepublicvoidrun(){
//在這寫操作webview的代碼
//請不要在這里放耗時代碼,否則會卡住UI線程
飢仿虧}
});
}catch(Exceptione){
}
}
}.start();
}
}
//PS:因為我已經不記得如果對象聲明在方法內部如何用final,所以索性寫成這樣。沒環境寫JAVA,所以可能有幾個小錯誤
⑦ android 新添加線程 怎麼讓他不再主線程里執行
子線程就是一個新的線程,不會再主線程執行,你說的是在主線程開啟子線程吧、
⑧ Android中是不是新開一個activity就是新建了一個線程
不是的,Android中所有的Activity都是在一個線叢攜程中,也就是我們所說的主帆隱線程(UI線程)。另外Activity 和 線程本身是兩個跨度很大的概念。滲轎伏
⑨ 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中的線程和線程池
一、除了Thread外,扮演線程角色的還有:AsyncTask和IntentService,同時HandlerThread也扮演特殊的線程。
IntentService:內部採用HandlerThread來執行,像一個後台線程,同時是一個服務,不容易被系統殺死。
二、HandlerThread的run方法是一個無限循環
三、IntentService中任務是排隊執行的
四、AsyncTask
1、Android1.6之前串悄段桐行執行任務,1.6時候採用線程池裡的並行,Android3.0開始又開始串列(為了避免並發錯誤),單任可以並行。
2、AsyncTask必須在UI線程調用(不過這個不是絕對的,和版本有關燃腔系,API 16之前,API 16到 22, API 22以後) 參考一
原因:內部有靜態Handler,採用UI線程的Looper來處理消息,這就是為什麼AsyncTask必須在UI線程調用,因為子線程默認沒有Looper無法創建下面的Handler,程序會直接Crash
3、AsyncTask中有兩個線程池和一個Handler,一個線程池用啟坦於任務排隊,一個線程池用於真正的執行任務,InternalHandler用於將
執行環境從線程池切換到主線程
AsyncTask串列與並行
五、線程池
線程池中多餘的線程是如何回收的