zoukankan      html  css  js  c++  java
  • 性能优化之_android多线程

    本文大纲为:

    如何创建线程

    线程间如何通讯

    线程间如何安全的共享信息

    一、线程的创建

    Thread在run方法中执行具体事务,或者传入一个runnable对象,但是不能调用view控件的更新方法,但是可以调用view控件的post方法

    Thread thread1 = new Thread("Thread1"){
            public void run() {
                //do something
            }
        };
        
        thread1.start();
        
        Thread thread2 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                mText.setText("hello world");// crash !!
            }
        });
        
        Thread thread3 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                
                mText.post(new Runnable() {
                    
                    @Override
                    public void run() {
                        mText.setText("hello world");// working !
                        
                    }
                });
            }
        });

    通过Thread的setPriority来设置线程的有限期,高优先级的线程会更快的执行,但是会影响到别的线程

    二、线程间通讯

    一般来说可以使用AsyncTask和handler/looper的机制来实现

    AsyncTask适合短时间异步执行的操作,复写下列方法

    doInbackground()//另一个线程中执行

    onPreExecute()

    onProgressUpdate(Progress... values)

    onPostExecute(Result result)

    onCancelled()

    AsyncTask中的任务是串行执行的,后面的任务要等前面的任务执行完毕才能开始执行。若需要改变这个机制,可以尝试使用executeOnExecutor方法

    Hanlder机制是Android中处理消息的经典机制。Handler类似于一个事件处理器同时也负责放置物体(message),MessageQueue是个传送带,Looper是使得传送带运转的动力,message即需要等待处理的货物

    可以另起一个带有Hanlder/Looper的Thread用来处理任务并且和主线程通讯,可以使用HanlderThread来创建避免出现一些异步任务导致的问题

    ublic class MyHandlerThread extends HandlerThread{
    
            private Handler handler;
            
            public MyHandlerThread(String name) {
                super(name);
                // TODO Auto-generated constructor stub
            }
            
            public Handler getHandler(){
                return handler;
            }
            
            @Override
            public synchronized void start() {
                super.start();
                
                Looper looper = getLooper();
                handler = new Handler(looper){
                    @Override
                    public void handleMessage(Message msg) {
                        switch(msg.what)
                        {
                        //do something
                        }
                    }
                };
                
            }
        }

    主线程可以这样子调用这个HandlerThead,以用来在子线程中执行一些操作,当然在HandlerThead的start方法中也可以执行主线程的Handler用来将结果返回

    MyHandlerThread subThread = new MyHandlerThread("sub-thread");
        
        private void dothings(){
            subThread.getHandler().sendMessage(msg);
        }

    三、线程间安全共享对象

    由于java内存模型的特殊,两个线程对同一个变量操作的时候,由于先是从内存中读取数据到寄存器,然后再将结果写回到内存中,若在thread1写回数据到内存前,另一个thread2已经写回过了数据,那么thread1再次写数据的话,这个时候结果对于thread2来说就是不对了

    所以就需要synchronized来同步 ,可以对方法或者代码块加锁,但是在synchronized中最好不要调用另一个同步代码块,否则可能会因为互相等待而导致死锁

    同步也可以用volatile来修饰变量实现

        private static volatile int mValue = 0;
        
        private void setValue(int n){
            mValue = n;
        }
        
        public static void loop(){
            while(mValue != 100){
                try{
                    Thread.sleep(1000);
                }catch(Exception e){
                    
                }
            }
        }
        

    这样子表示每次读取mValue这个值的时候都要等待读取最终的值

    在Activity中使用AsyncTask会出现一个问题,如果task正在执行,而这个时候屏幕旋转了,导致Activity重建。那么这个时候task里面的context的对象都是过时得了,会造成各种问题。

    解决方法就是在onSaveInstance或者onRetainNonConfiguration中返回这个task的handle,在Activty的onCreate中重新进行判断。

    参考资料
    带有Handler的子线程执行操作:

    http://www.cnblogs.com/allin/archive/2010/05/19/1738800.html

    线程池

    http://www.cnblogs.com/yezhenhan/archive/2012/01/07/2315645.html

    Activity和AsyncTask

    http://blog.csdn.net/java2009cgh/article/details/7008983

  • 相关阅读:
    一小段代码体现出的编程艺术
    2013年:第十一届软交会今天开始
    干掉baidu地图Logo的CSS
    编程语言历史,你属于几零后?
    WebServer实现SQL数据库百度坐标转换转化的算法
    使用Nginx代理Ext.net2.0异步请求报错问题
    PostgreSQL9.3新增的json_populate_recordset函数使用问题
    坐标转换服务笔录
    关于extjs中文乱码和emptyText的问题
    百度地图Polyline画直线BUG
  • 原文地址:https://www.cnblogs.com/soaringEveryday/p/4347391.html
Copyright © 2011-2022 走看看