【问题标题】:Access shared data with handler使用处理程序访问共享数据
【发布时间】:2023-04-10 06:41:02
【问题描述】:

在我的 Android 项目中,我有一个注册了 BroadcastReceiver 的类:

public MyClass {
     private MyData mData;

     public MyClass(Context context) {
        mData = GET_PERSISTED_DATA(); 
        //code to register receiver
        ...
        context.registerReceiver(myReceiver, filter);
     }

     public void accessData() {
        //Code to access mData
        ...
     }

     private BroadcastReceiver myReceiver=  new BroadcastReceiver() {

        @Override
        public void onReceive (Context context, Intent intent) {
                    //This is called in main UI thread
                    accessData();
             }

}

如上所见,在myReceiveronReceive() 中,它调用accessData() 方法来访问mData然而,还有另一个工作线程(除了主线程)也可以调用accessData() 方法。这意味着它不是线程安全的。

由于Handler 会一一处理来自消息队列的消息,我可以通过以下方式使用Handler 来使上述情况成为线程安全的吗?还是有更优雅的方式?

public MyClass {
         private MyData mData;
         private Handler mHandler;

         public MyClass(Context context) {
            mData = GET_PERSISTED_DATA(); 
            //code to register receiver
            ...
            context.registerReceiver(myReceiver, filter);
            mHandler = new MyHandler();
         }

         public void accessData() {
            mHandler.sendMessage(mHandler.obtainMessage(1));
         }

         private class MyHandler extends Handler() {
             @Override
             void handleMessage(Message msg){
                 if(msg.what == 1){
                    //Code to access mData
                     ...
                 }

             }
         }

         private BroadcastReceiver myReceiver=  new BroadcastReceiver() {

            @Override
            public void onReceive (Context context, Intent intent) {
                        //This is called in main UI thread
                        accessData();
                 }

    }

通过上述方式使用处理程序,我现在线程安全吗?

【问题讨论】:

    标签: java android multithreading android-handler


    【解决方案1】:

    如果方法 accessData() 很快,那么只需将其声明为同步。如果它是长时间运行的,那么,除了声明它同步之外,还要注意从 onReceive() 调用时它正在运行的线程,因为默认情况下 onReceive() 是在主(UI)线程上调用的,而这个线程不能被占用了很长时间。如何在主线程之外执行长时间运行的工作在别处进行了描述。

    附加: 您的实现可能有效,但有一些缺陷:实际执行由 accessData() 引起的工作的线程是执行 MyClass 的构造函数的线程。首先,这是一个糟糕的设计:初始化线程可能会改变,程序可能会停止工作,因为新线程可能没有 Looper。然后,初始化线程是 UI 线程,这意味着即使是工作线程也将工作委托给 UI 线程,而通常 UI 线程必须从任何非 UI 工作中释放出来。

    处理程序和循环器不是应尽可能使用的通用方法。首先学习多线程编程的基础知识,你会发现没有它们你也可以活下去。

    【讨论】:

    • 谢谢,但我也想知道以我发布的方式使用处理程序是线程安全的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 2012-01-19
    • 1970-01-01
    • 2017-06-22
    相关资源
    最近更新 更多