文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

深入Android线程的相关问题解惑

2022-06-06 10:47

关注

一个应用只有一个线程
在默认情况下,更确切的讲一个进程中只有一个线程,这跟其他语言,比如C/C++,Java等是一致。也就是说在Android应用程序里面一个进程只有一个线程,所有组件都运行在一个线程里面!
当应用程序启动时,系统会为其创建一个进程,也会创建一个线程名字叫做main,所有其所属组件的创建,系统事件的处理,系统的回调等一切应用相关的事情都运行在此名叫main的线程中。此线程即为常说的主线程(main thread)。俗称的UI线程(UI thread)也是它,因为只有主线程可以操作UI相关的事情,所以有人把主线程也称作UI线程,但这并不是正确的说法,因为Service所属的线程也可以操作Toast,但是Service并没有UI。为什么非主线程不能操作UI呢?因为对UI操作常常会引发系统的回调,所以如果允许第三线程来操作可能会引发系统回调的紊乱,进而会打乱整个框架的时序!
这里要特别注意的就是同一个进程中的所有组件运行在同一个线程中,Activiy,Service,BoradcastReceiver和ContentProvider都运行在主线程中。
最容易引起误解的就是Service,文档和常识都会认为Service是放在后台用于操作费时运算的,但是实则不然,如果你在Service中做费时操作,同样会引发臭名昭著的ANR(Application Not Responding)。所以如果想把Service当做一个Server,必须在Service用HandlerThread或Thread创建一个Worker线程!
Activity也是一样的,你startActivity()后,开启了一个新的Activity,但它们都运行在同一个线程中,所以你还是不能在原Activity中做费时操作!也即在调用startActivity()开启了一个新的Activity后,或者在onPause(), onStop(), onDestroy()中做费时操作会引发ANR。
对于ContentProvider也是一样的,如果跟其他组件在同一进程内,那么调用ContentResolver的方法会相当于直接调用ContentProvider的方法。如果是在另外一个进程中,虽是通过IPC,但也是同步的,因为IBinder的同步的,也即调用ContentResolver时会把调用者的进程挂起,等待ContentProvider的进程操作结束,再把结果传给调用者进程!所以,如果ContentProvider中有费时操作,或者会同步锁数据库等,也一定要注意ANR的发生!
所以一定要记住:一个进程只有一个线程,所有组件都运行在主线程中。
因此,如果有费时操作,必须要创建Worker线程!

实例
下面有一个小实例,一个应用中有五个组件:2个Activity,一个Service,一个ContentProvider和一个BroadcastReceiver。在每个组件的方法中都有打印所属线程信息,另外对于Activity,Service和ContentProvider如果做费时操作会引发ANR,对于BroadcastReceiver更是如此,这个大家都懂得的!
代码如下:
public class ActivityDemo extends Activity {
    private static final String TAG = "ActivityDemo";
    private Handler mMainHandler = new Handler(new Handler.Callback() {
 public boolean handleMessage(Message msg) {
     dumpThreadInfo();
     return false;
 }
    });
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 dumpThreadInfo();
 super.onCreate(savedInstanceState);
 // add four buttons
 LinearLayout layout = new LinearLayout(getApplication());
 layout.setOrientation(LinearLayout.VERTICAL);
 Button startService = new Button(getApplication());
 startService.setText("Start a Service");
 startService.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  Intent i = new Intent(getApplication(), ServiceDemo.class);
  startService(i);
     }
 });
 layout.addView(startService);
 Button startAnother = new Button(getApplication());
 startAnother.setText("Start another Activity");
 startAnother.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  Intent i = new Intent(getApplication(), AnotherActivity.class);
  startService(i);
     }
 });
 layout.addView(startAnother);
 Button startContentProvider = new Button(getApplication());
 startContentProvider.setText("Start a ContentProvider");
 startContentProvider.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  getContentResolver().query(ContentProviderDemo.CONTENT_URI, null, null, null, null);
     }
 });
 layout.addView(startContentProvider);
 Button startReceiver = new Button(getApplication());
 startReceiver.setText("Start a BroadcastReceiver");
 startReceiver.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  Intent i = new Intent("android.action.start_broadcastreceiver_demo");
  sendBroadcast(i);
     }
 });
 layout.addView(startReceiver);
 setContentView(layout);
 mMainHandler.sendEmptyMessageDelayed(0, 500);
    }
    public void dumpThreadInfo() {
 Thread.dumpStack();
 Log.e(TAG, Thread.currentThread().toString());
 Log.e(TAG, " " + getMainLooper());
    }
}

代码如下:
public class AnotherActivity extends Activity {
    private static final String TAG = "AnotherActivity";
    private Handler mMainHandler = new Handler(getMainLooper(), new Handler.Callback() {
        public boolean handleMessage(Message msg) {
            // this will cause ANR
            Log.e(TAG, "you know what this is very slow slow slow slow");
            SystemClock.sleep(20 * 1000);
         &nbs p;  dumpThreadInfo();
            return false;
        }
    });
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 dumpThreadInfo();
 super.onCreate(savedInstanceState);
 setTitle("this is another activity");
 mMainHandler.sendEmptyMessageDelayed(0, 500);
    }
    @Override
    protected void onDestroy() {
 dumpThreadInfo();
 super.onDestroy();
    }
    public void dumpThreadInfo() {
 Thread.dumpStack();
 Log.e(TAG, Thread.currentThread().toString());
 Log.e(TAG, " " + getMainLooper());
    }
}

代码如下:
public class ServiceDemo extends Service {
    private Handler mMainHandler = new Handler(new Handler.Callback() {
        public boolean handleMessage(Message msg) {
            // this will cause ANR, too
            Log.e(TAG, "this is very slow you know, slow slow");
            SystemClock.sleep(20 * 1000);
            dumpThreadInfo();
            return false;
        }
    });
    private static final String TAG = "ServiceDemo";
    @Override
    public IBinder onBind(Intent arg0) {
 dumpThreadInfo();
 return null;
    }
    @Override
    public void onCreate() {
 dumpThreadInfo();
 super.onCreate();
 mMainHandler.sendEmptyMessageDelayed(0, 500);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
 dumpThreadInfo();
 return super.onStartCommand(intent, flags, startId);
    }
    public void dumpThreadInfo() {
 Thread.dumpStack();
 Log.e(TAG, Thread.currentThread().toString());
 Log.e(TAG, " " + getMainLooper());
    }
}

代码如下:
public class ContentProviderDemo extends ContentProvider {
    public static final Uri CONTENT_URI = Uri.parse("content://com.hilton.effectiveandroid.app/content");
    private static final String TAG = "ContentProviderDemo";
    @Override
    public int delete(Uri arg0, String arg1, String[] arg2) {
 dumpThreadInfo();
 return 0;
    }
    @Override
    public Uri insert(Uri uri, ContentValues values) {
 dumpThreadInfo();
 return null;
    }
    @Override
    public boolean onCreate() {
 dumpThreadInfo();
 return false;
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
 dumpThreadInfo();
 // it will cause ANR of course
 Log.e(TAG, "this is very slow, you know that");
 SystemClock.sleep(20 * 1000);
 return null;
    }
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
 dumpThreadInfo();
 return 0;
    }
    public void dumpThreadInfo() {
 Thread.dumpStack();
 Log.e(TAG, Thread.currentThread().toStri ng());
    }
    @Override
    public String getType(Uri arg0) {
 return null;
    }
}

代码如下:
public class BroadcastReceiverDemo extends BroadcastReceiver {
    private static final String TAG = "BroadcastReceiverDemo";
    @Override
    public void onReceive(Context context, Intent intent) {
 Log.e(TAG, "intent is " + intent);
 dumpThreadInfo();
    }
    public void dumpThreadInfo() {
 Thread.dumpStack();
 Log.e(TAG, Thread.currentThread().toString());
    }
}

您可能感兴趣的文章:android开发教程之子线程中更新界面android开发教程之handle实现多线程和异步处理android使用handler ui线程和子线程通讯更新ui示例android使用handlerthread创建线程示例android使用多线程更新ui示例分享Handler与Android多线程详解浅析android中的线程封装android中多线程下载实例Android多线程及异步处理问题详细探讨Android多线程处理机制中的Handler使用介绍Android中加载网络资源时的优化可使用(线程+缓存)解决Android开发笔记之:如何安全中止一个自定义线程Thread的方法Android 在其他线程中更新UI线程的解决方法深入Android Handler与线程间通信ITC的详解Android开发笔记之:深入理解多线程AsyncTaskAndroid Handler主线程和一般线程通信的应用分析android 多线程技术应用android开发教程之使用线程实现视图平滑滚动示例


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯