• Android 线程间通信


    进程与线程的区别?

      在Android中,线程是跑在进程之中的,当手机打开一个APP就相当于打开了一个进程,比如:UI界面的更新,就是在主线程中完成的,我也可以自定义一些子线程来完成所需要的任务.

    如何创建线程?创建线程的几种方式?

      1.创建一个类继承Thread类

      2.创建一个类实现Runnable接口

    什么是多线程?

      线程是程序中一个单一的顺序控制流程,在程序中同是运行多个线程完成不同的工作,称为多线程

    ANR的基础知识及产生?

      ANR:application not responding :应用程序无响应

      产生的情况:1.主要类型按键或触摸事件在特定的时间(5秒)内无响应

            2.BroadcastReceiver在特定事件(10秒)内无法处理完成

            3.小概率类型Service在特定事件内无法完成

    线程的状态:

      创建(new) ---->就绪(runnable)---->运行(running)---->阻塞(bloocked)----->消亡(dead)

      当线程满足所需要运行的条件时,才能进入就绪状态

      当线程就如就绪状态后,不能马上获得cpu的执行时间,需要CPU进行资源分配

      当线程被中断后执行完毕才会被消亡

    线程的生命周期

     

    注意:多线程会导致CPU资源分配的增加导致系统繁忙

    多线程示例:售票

    package com.hejun.ticket;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
        final static String TAG = "MainActivity";
        private Button button;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            button = findViewById(R.id.strat_sale);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SaleTickets saleTickets1 = new SaleTickets(4);
                    SaleTickets saleTickets2 = new SaleTickets(3);
                    SaleTickets saleTickets3 = new SaleTickets(2);
                    SaleTickets saleTickets4 = new SaleTickets(2);
                    saleTickets1.setName("售票窗口1");
                    saleTickets2.setName("售票窗口2");
                    saleTickets3.setName("售票窗口3");
                    saleTickets4.setName("售票窗口4");
                    saleTickets1.start();
                    saleTickets2.start();
                    saleTickets3.start();
                    saleTickets4.start();
    
                }
            });
        }
        private class SaleTickets extends Thread{
            private int tickets;
            private SaleTickets(int tickets){
                this.tickets = tickets;
            }
            @Override
            public void run() {
                super.run();
                while(tickets>0){
                    Sale();
                }
                Log.d(TAG, Thread.currentThread().getName()+ "的票售卖完了");
            }
            private void Sale(){
                tickets--;
                Log.d(TAG, Thread.currentThread().getName()+ "正在卖票,还剩下"+ tickets +"张票");
            }
        }
    }

    演示结果

      

    线程间通信的相关组件

      1.Message :消息.其中包含了消息ID,消息处理对象以及处理数据,Message有MessagesQueue统一列队,最终有Handle处理

      2.Handle:处理者,负责Message的发送及处理,实现handleMessage(Message msg)方法,对特定的MEssage进行处理

      3.MessagesQueue:消息队列,用来存放Handle发送过来的消息,并按照先进先出规则执行

      4.Looper:消息泵,不断的从MessagesQueue中抽取Message执行,一个MessagesQueue需要一个Looper

      5.Thread:线程,辅助调度整个消息循环,即消息循环执行的场所

    关系:Handle looper  MessagesQueue是简单的三角关系Looper和MessagesQueue是一一对应的

    消息循环

      一个Message经由Handle发送到MessagesQueue队列中,再由Looper不断的从MessagesQueue抽取,又再一次回到Handle的环抱,实现线程间的通信

    线程与更新

      在ui线程中,如果创建Handle是不传入Looper对象,那么将直接使用UI线程的Looer对象(系统已经帮我们自动创建了),在其他线程创建Handle如果不传入Looper对象,那么Handle将不能接收处理消息,在这种情况下,通常的做法是:

    在创建Handle之前,为该线程准备好一个Looper(Looper.prepare),然后让这个Looper跑起来(Looper.loop),这样Handle 才能正常工作;.

    注意:Handle处理消息总是在创建Handler的线程中执行,而我们的消息处理,不乏UI的更新操作,不正确的线程直接更新UI将引发异常,因此,我们需要时刻关心Handler是在哪个线程中创建的.

    SDk提供四中方式可以从其他线程中访问UI线程

      1.Activity.runOnUiThread(Runnable)

      2.View.post(Runnable)

      3.View.postDelayed(Runnable,long)

      4.Handler

    案例,从网上下载图片并更新进度

    package com.hejun.ticket;
    
    import android.annotation.SuppressLint;
    import android.app.ProgressDialog;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Handler;
    import android.os.Message;
    import android.os.SystemClock;
    import android.os.Trace;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class DownPicture extends AppCompatActivity {
        final static String address = "http://img4.imgtn.bdimg.com/it/u=1952016862,1880307894&fm=26&gp=0.jpg";
        private static final String TAG = "DownPicture";
        private Handler mMainHandler = null;
        private int progress;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_down_picture);
            Button button = findViewById(R.id.button);
            final ImageView imageView = findViewById(R.id.img);
            button.setOnClickListener(new View.OnClickListener() {
                @SuppressLint("HandlerLeak")
                @Override
                public void onClick(View view) {
                    final ProgressDialog progressDialog = new ProgressDialog(DownPicture.this);
                    progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                    progressDialog.setMessage("下载中");
                    progressDialog.setMax(100);
                    progressDialog.show();
                    new Thread(new Down(),"下载图片").start();
                    mMainHandler = new Handler(){
                        @Override
                        public void handleMessage(Message msg) {
                            super.handleMessage(msg);
                            switch (msg.what){
                                case 10010:
                                    progressDialog.setProgress(msg.arg1);
                                    break;
                                case 10011:
                                    progressDialog.dismiss();
                                    Bitmap bitmap = (Bitmap) msg.obj;
                                    imageView.setImageBitmap(bitmap);
                                    break;
                            }
                        }
                    };
                }
            });
        }
    
        class Down implements Runnable {
        String fileName = "dowmPicture";
            @Override
            public void run() {
                try {
                    URL url = new URL(address);
                    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                    httpURLConnection.setConnectTimeout(5000);
                    httpURLConnection.setRequestMethod("GET");
                    if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        InputStream inputStream = httpURLConnection.getInputStream();
                        OutputStream outputStream = openFileOutput(fileName, MODE_PRIVATE);
                        byte[] bytes = new byte[1024*1024];
                        int s = httpURLConnection.getContentLength();
                        int d = 0;
                        int curent = 0;
                        while ((d = inputStream.read(bytes)) != -1){
                            outputStream.write(bytes,0,s);
                            curent +=  d;
                            progress = (int) ((float)curent/s*100);
                            Log.d(TAG, "当前现在进度为" + progress);
                            SystemClock.sleep(40);
                            Message message  = new Message();
                            message.arg1 = progress;
                            message.what = 10010;
                            mMainHandler.sendMessage(message);
                        }
                        if (progress == 100){
                            Bitmap bitmap = BitmapFactory.decodeFile(getFileStreamPath(fileName).getAbsolutePath());
                            Message message  = new Message();
                            message.obj = bitmap;
                            message.what = 10011;
                            mMainHandler.sendMessage(message);
                        }
    
    
                        inputStream.close();
                        outputStream.close();
                        httpURLConnection.disconnect();
                    }
    
                }
                catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

  • 相关阅读:
    tomcat war包自动化部署脚本
    nginx只允许域名访问,禁止ip访问
    Nginx Errors: upstream response cache error
    Linux进程的睡眠和唤醒
    传输层:UDP 协议
    IP网际协议
    应用层协议
    [Eclipse插件] Eclipse设置Tab键为空格(ctrl+shirt+f格式化生效)!
    [Android Pro] 使用CursorLoader异步加载数据 from 3.0
    [Android Memory] 内存分析工具 MAT 的使用
  • 原文地址:https://www.cnblogs.com/conglingkaishi/p/9939008.html
Copyright © 2020-2023  润新知