• 安卓中多线程


    Java中多线程:

      http://www.cnblogs.com/NeilZhang/p/6831636.html

    开辟子线程,同时在子线程中发送消息,在主线程中处理消息。 

     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
                     handler0 = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        doSomeThing();
                    }
            };
            new myThread().start();
        }
    
        public class myThread extends Thread{
            @Override
            public void run() {
                super.run();
                Looper.prepare();    
                Message mss = new Message();
                mss.obj = "test in handler";
                Log.d(TAG, "run: "+Thread.currentThread().getId());
                handler0.sendMessage(mss);
                Looper.loop();
            }
        }

    另一种写法是:在MyThread中初始化handler0,增加 Looper.prepare() 和 Loop.loop();

       public class myThread extends Thread{
            @Override
            public void run() {
                super.run();
                Looper.prepare();
                handler0 = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Log.d(TAG, "handleMessage: in myThread"+msg+"   "+Thread.currentThread().getId());
                    }
                };
                Message mss = new Message();
                mss.obj = "test in handler";
                Log.d(TAG, "run: "+Thread.currentThread().getId());
                handler0.sendMessage(mss);
                Looper.loop();
            }
        }
    View Code

    当 new MyThread().start();   发送消息和处理消息都是在同一个进程中进行的。

    这种方法似乎没有任何意义,实际应用不多。

    进程1 发送消息给进程2  , 进程2 处理进程1发的消息,同时给 进程1 发送消息。

    两个线程之间进行了通信。

     class MyThread1 extends Thread {
    
            @Override
            public void run() {
                super.run();
    
                Looper.prepare();
    
                handler1 = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Log.d(TAG,"threadName--" + Thread.currentThread().getId() + "messageWhat-"+ msg.what );
                    }
                };
    
                try {
                    sleep( 3000 );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                handler2.sendEmptyMessage( 2 ) ;
                Log.d(TAG, "run: Mythread1 :"+Thread.currentThread().getId());
                Looper.loop();
            }
        }
    
        class MyThread2 extends Thread {
            @Override
            public void run() {
                super.run();
                Looper.prepare();
    
                handler2 = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Log.d(TAG,"threadName--" + Thread.currentThread().getId() + "messageWhat-"+ msg.what );
                    }
                };
    
                try {
                    sleep( 4000 );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                handler1.sendEmptyMessage( 5 ) ;
                Log.d(TAG, "run: Mythread2 :"+Thread.currentThread().getId());
                Looper.loop();
            }
        }
    View Code

    在程序中开启两个进程:

      new MyThread1().start();
      new MyThread2().start();

    运行的结果:
      

                          

    总结:

      1、调用Looper类的 prepare() 方法可以为当前线程创建一个消息循环,调用loop() 方法使之处理信息,直到循环结束。

      2、Handler有几个构造重载,如果构造时不提供Looper类对象参数,会获取当前线程的Looper对象,即将当前线程的消息循环作为Handler关联的消息循环。

      3、消息处理机制中,消息存放在一个消息队列中,而线程围绕这个队列进入一个无限循环,直到程序退出。

        如果队列中有消息,线程就会把消息取出来,并分发给相应的Handler进行处理;

          如果队列中没有消息,线程就会进入空闲等待状态,等待下一个消息的到来。

    强化:主线程子线程中的通信

        private void init3() {
            mTextView = (TextView) findViewById(R.id.text);
            Log.d(TAG, "init:   "+Thread.currentThread().getId());
            //1 子线程发送消息给本身
            new Thread() {
                public void run() {
                    long temp = Thread.currentThread().getId();
                    Log.d(TAG, "run: "+temp);
                    Looper.prepare();
                    mHandlerTest1=new HandlerTest1();
                    Message message = new Message();
                    message.obj = "子线程发送的消息Hi~Hi";
                    mHandlerTest1.sendMessage(message);
                    Looper.loop();
                }
            }.start();
        }
    
        private class HandlerTest1 extends Handler {
            private HandlerTest1(Looper looper) {
                super(looper);
            }
            private HandlerTest1(){
                super();
            }
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                System.out.println("子线程收到:" + msg.obj);
    
                Log.d(TAG, "handleMessage: in handlerTest1 : "+ Thread.currentThread().getId());
                //2  收到消息后可再发消息到主线程
                mHandlerTest2=new HandlerTest2(getMainLooper());
                Message message = new Message();
                message.obj = "O(∩_∩)O";
                mHandlerTest2.sendMessage(message);
            }
        }
    View Code

    注意:

      mHandlerTest2=new HandlerTest2(getMainLooper());

    通过getMainLooper()函数获取主线程中的 消息队列,所以,

    mHandlerTest2发送的消息都会发送到主线程中去。运行 Init3函数的结果为:

    handlerTest2 在主线程中运行, handerler1在开辟的子线程中运行。
    HandlerThread 用法:
     private void init4(){
            //创建一个线程,线程名字:handler-thread
            myHandlerThread = new HandlerThread( "handler-thread") ;
            //开启一个线程
            myHandlerThread.start();
            //在这个线程中创建一个handler对象
            Log.d(TAG, "init4: "+Thread.currentThread().getId());
            handler3 = new Handler( myHandlerThread.getLooper() ){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    //这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
                    Log.d(TAG , "消息: " + msg.what + "  线程: " + Thread.currentThread().getId()  ) ;
                }
            };
    
            //在主线程给handler发送消息
            handler3.sendEmptyMessage( 1 ) ;
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "new runnable "+Thread.currentThread().getId());
                    //在子线程给handler发送数据
                    handler3.sendEmptyMessage( 2 ) ;
                }
            }).start() ;
        }
    View Code
    
    

                                        

    •   在上述代码中,通过HandlerThread开启一个新的线程,将主线程中的Loop转到子线程中处理,降低了主线程的压力,

    使主界面更流畅。  它有自己的MessageQueue不会干涉主线程中的消息队列。

    •   程序中如果将此HandlerThread注释掉,程序会出错,因为它会在主线程中发消息给主线程去处理。
    •  在HandlerThread内部消息,处理任务是串行执行,消息是顺序到达的。当队列中某个任务执行时间较长时,后续的任务就会被延迟处理。


      上述程序的github地址为:(AndroidStudio项目)

        git@github.com:lsfzlj/AndroidTestProject.git

    后台开启线程的函数写法:

    更加简洁明了:

    public class BackTaskRunner {
        private static final String TAG = "BackTaskRunner";
        private HandlerThread handlerThread;
        private Handler handler;
    
        private BackTaskRunner() {
            handlerThread = new HandlerThread(TAG);
            handlerThread.start();
            handler = new Handler(handlerThread.getLooper());
        }
    
        public static Handler getHandler() {
            return SingletonHolder.sRunner.handler;
        }
    
        private static class SingletonHolder {
            static BackTaskRunner sRunner = new BackTaskRunner();
        }
    }

    调用方法:

     BackTaskRunner.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    Logging.d(TAG, "pay() start UNPay");
                    //最后一个参数: "01" 代表测试环境    "00" 代表正式环境
                    UPPayAssistEx.startPay(activity,null,null,tn,payMode);
                }
            });
  • 相关阅读:
    虚拟机Linux环境搭建所遇到的 问题
    Java-字节流读写文件
    [ZJOI2019]语言
    [CTSC2006]歌唱王国
    CF500F New Year Shopping
    CF438E The Child and Binary Tree
    [GXOI/GZOI2019]旧词
    [LNOI2014]LCA
    [CTSC2017]吉夫特
    [SDOI2014]旅行
  • 原文地址:https://www.cnblogs.com/NeilZhang/p/7078930.html
Copyright © 2020-2023  润新知