如何結束一個線程?html
關於線程的結束有如下幾點:java
1.不要手動調用stop方法強行終止一個線程,這種方式不安全。android
經過幫助文檔,咱們能夠知道,Android的線程類自己就提供了一些公共方法去結束線程。api
final void stop()安全
This method is deprecated. because stopping a thread in this manner is unsafe and can leave your application and the VM in an unpredictable stateapp
可是,經過說明咱們能夠看到,這些方法Android自己都是不推薦使用的,經過這種方式結束線程是不安全的。異步
2.線程裏run函數短,執行完後線程會自行銷燬,不用手動去終止。ide
3.手動中止,經過在run裏設置標誌先中止運行,再調用Thread.interrupt();注意,在run沒有中止時調用.interrupt()沒有效果。函數
android中關閉線程的的三種方法教程詳解
性能
1. 本身加入一個成員變量, 咱們在程序的循環裏面, 輪流的去檢查這個變量, 變量變化時,就會退出這個線程. 代碼示例以下
-
- package com.test;
-
- public class StopThread extends Thread {
-
- private boolean _run = true;
- public void stopThread( boolean run) {
- this ._run = !run;
- }
-
- @Override
- public void run() {
- while(_run) {
-
- //[img]http://www.blogjava.net/Images/dot.gif[/img]數據處理
-
複製代碼
2. 方法1 雖然能夠能夠處理好, 不過, 在有阻塞線程的語句的時候每每不能處理好. 好比, 設計到Socket的阻塞語句. 雖然java有提供異步io可是異步io是在程序裏不斷去查詢有沒有消息的, 因此耗電量可想而知, 對手機這種設備來講每每不適用.
那麼阻塞的語句,怎麼終止線程呢?
Java雖然deprecate了一個stop,可是,提供了interrupt(),這個方法是安全的. 這個中斷方法能夠將阻塞的線程喚醒過來, 可是注意 他不能將非阻塞的線程中斷. 中斷的同時,會拋出一個異常InterruptedException. 幸運的是, SocketChannel.connect() .read() 阻塞方法都會接受中斷,ClosedByInterruptException.
這時咱們不輪詢變量了, 輪詢當前線程是否被中斷, 代碼
-
- System.out.println("start");
- while(!this.isInterrupted()) {
- [img]http://www.blogjava.net/Images/dot.gif[/img]數據處理
-
-
- }
- }catch (Exception e) {
- e.printStackTrace();
- }
- System.out.println(stop);
- super.run();
- }
-
- public static void main(String[] args) {
- StopThread thread=new StopThread();
- thread.start();
- try {
- Thread.sleep(1000);
- }catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- thread.interrupt();
- System.out.println(interrupt);
- }
- }
-
複製代碼
3. Android 在本身的Api中加入了,Process類, 這個類能夠直接終結進程, 也就是當前線程所在的JVM.
final static void killProcess(int pid) 其中,pid, 能夠經過Process.mypid() 獲取, 但這樣終結的是整個程序, 不是咱們所想要的.
==================================================分割線==========================================
若是該線程處在不可中斷狀態下,就是沒有調用上述api,那麼java只是設置一下該線程的interrupt狀態,其餘事情都不會發生,若是該線程以後會調用行數阻塞API,那到時候線程會馬會上跳出,並拋出InterruptedException,接下來的事情就跟第一種情況一致了。若是不會調用阻塞 API,那麼這個線程就會一直執行下去。除非你就是要實現這樣的線程,通常高性能的代碼中確定會有wait(),yield()之類出讓cpu的函數,不會發生後者的狀況。
-
- readCacheThread = new Thread(){
- public void run() {
-
- try {
- Method getPackageSizeInfo = pm.getClass().getMethod(
- "getPackageSizeInfo", String.class,
- IPackageStatsObserver.class);
- for (AppInfoItem item : installedApp) {//我的應用
- sleep(1);//interrupt後會拋異常,這樣就能夠提早結束線程
- getPackageSizeInfo.invoke(pm, item.packageName, pkgsizeobserver);
- }
- for (AppInfoItem item : systemApp) {//系統應用
- sleep(1);
- getPackageSizeInfo.invoke(pm, item.packageName, pkgsizeobserver);
- }
-
- } catch (Exception e) {
- // TODO: handle exception
- e.printStackTrace();
- Log.e("qqqqqqqqqqqqq", "sleep over");
- return;
- }
-
- };
- };
- readCacheThread.start();
-
複製代碼
在須要中斷線程的地方調用:
-
- if(readCacheThread != null && readCacheThread.isAlive()){
- //Log.e("readCacheThread", "thread interrupt_1");
- readCacheThread.interrupt();
- //Log.e("status", ""+readCacheThread.isInterrupted());
- }
-
複製代碼
(用判斷readCacheThread.isInterrupted()方法會失敗,由於總是返回false,不知道爲何。因此只能用sleep()而後捕獲異常再退出)。
這樣即可提早退出一個線程。