浅谈Android中的线程

来源:互联网 发布:实况贝克汉姆捏脸数据 编辑:程序博客网 时间:2024/05/06 10:06

      刚开始学的时候,看见handler或者thread就开始犯蒙,其实不难的东西就是自己理不清思路。因为我是自学的,很多知识都只是囫囵吞枣,简单记录一下我理解的线程,算是自己的梳理,也给像我这样的初学者一些启发。

      说一个形象一点的解释,线程就好比我们让别人帮我们干活:我现在在这里打字,口渴了,想让另一个人帮我拿杯水,我就好比是主线程,我还是在这里做我的事情,另外帮我拿水的就好比我的子线程,既不耽误我继续做我的工作,又能解决我不想做的浪费时间的事情。

      一个android应用就是一个Linux进程,每个应用在各自的进程中运行,互不干扰,比较安全。

      一个应用对应一个主线程,就是通常所说的UI线程,android遵守的就是单线程模型,所以说Ui操作不是线程安全的。在 单线程的模型下,一些耗时的操作就要交给其它子线程去执行。于是就有了Message Queue(消息队列),辅助线程间进行通信。而线程,就是为了解决我们遇到的浪费时间的事情,如果把一些耗时的操作放到主线程中就会造成 ANR(ANR:Application Not Responding,应用程序无响应)。每个线程都可以有自己的Message Queue,每个MessageQueue都会有一个对应的handler,其它子线程中要想有自己的消息队列必须手动生成。管理消息队列的是 Looper,每个进程都有自己的Looper。子线程中Message Queue 的生成必须依赖于Looper,Looper一旦开始loop后,它就会一直监控着消息队列,对send进来的Message进行处理。message的 处理采用先进先出原则。一旦处理完一条Message,那么该Message马上就会被置为null。当传送过来很多的消息时,不知道交给哪个线程执行 时,可以判断当前这个传送消息过来的handler里面的Looper对象是属于哪个线程的,属于哪个线程就在哪个线程里执行。

      不知道大家是不是被上面的话绕晕了,简单的说,程序运行时只能有一个主线程但可以有若干个子线程。UI线程就是MainThread主线程,而其他的线程就属于WorkThread,我们在WorkThread中通过Handler发送消息Msg,消息放到消息队列中,Looper取出消息并交给Handler来处理,而转交给Handler处理时,就回到了MainThread中,我们就可以进行一些UI的操作了。至此,就建立起了WorkThreadMainThread的通讯机制。

下面我们就以倒计时为例,来简单了解线程的用法。首先要为按钮绑定一个监听:

bt1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (timestopflag) {timestopflag = false;// 生成一个线程对象Thread timethread = new TimeThread();// 启动线程timethread.start();bt1.setText("暂停计时");} else {timestopflag = true;bt1.setText("开始计时");}}});

之后新建一个线程,将秒数时间传进去,让线程沉睡,每过一秒减一秒。(不知道为什么这一段一写成代码格式就保存不了)

        public void run() {

            while (true) {
                if (timestopflag) {
                    break;
                }
                String timestr = null;
                try {
                    Thread.sleep(1000);
                    time = time - 1000;
                    if (time < 0) {
                        time = 0;
                        break;
                    }
                    timestr = TimeFmort(time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // Message msg = new Message();
                // 用handler获取一个message对象
                Message msg = handler.obtainMessage();
                // 将时间传给msg
                msg.obj = timestr;
                // 将message发送到消息队列,交由handleMessage处理消息对象
                handler.sendMessage(msg);
            }

        }

private String TimeFmort(long time) {        String timestr;        Date date = new Date(time);        String second, mit;        if (date.getMinutes() < 10) {            mit = "0" + date.getMinutes();        } else {            mit = date.getMinutes() + "";        }        if (date.getSeconds() < 10) {            second = "0" + date.getSeconds();        } else {            second = date.getSeconds() + "";        }        timestr = "0" + (date.getHours() - 8) + ":" + mit + ":" + second;        return timestr;    };
最后我们新建一个handler,接受到线程传过来的msg,并进行处理。
Handler handler = new Handler() {public void handleMessage(Message msg) // 接受到线程传过来的msg,并进行处理String time = msg.obj.toString();if (time.equals("00:00:00")) {tv1.setText("计时结束");} else {tv1.setText(msg.obj.toString());}};};

上 面是一个简单是倒计时的例子,TimeThread就是一个子线程,我们让线程沉睡,每1秒减少一次,并把秒数转换成00:00:00格式的字符串 timestr,在子线程中,通过Message msg = handler.obtainMessage();获取message对象(或者Message msg = new Message();创建一个对象,我还不知道这俩有啥不一样),把时间数据通过msg.obj = timestr;放入msg里 ,通过handler.sendMessage(msg);发送出去。handleMessage方法接到数据就可以更新textview里面是时间啦, 这样一个简单的线程传送消息就完成了。

如果我哪里写的不对或者不明白,欢迎大家留言指正,不胜感激~


倒计时源码


0 0
原创粉丝点击