Java中的线程

1. 线程的两种实现方式

①继承Thread类

②实现Runnable接口

两者区别在于,Thread这个类的对象,代表的是一个线程,而Runnable的对象,代表的是线程体(也就是线程要执行的代码)。

2.线程的生命周期

创建---调用start()进入就绪状态---抢占到CPU就开始进入运行状态---运行过程中被别的线程抢到CPU,或者遇到阻塞,则进入就绪状态---如果执行完线程体,则进入死亡状态

线程死亡之后,不可能再复活。

3.多线程同步

如果多个线程访问同一个资源,会产生多个线程竞争一个资源,则会产生多线程错误,这时需要通过同步方式来解决,使用synchronized关键字,采用同步代码块或者同步方法。

所谓的同步,就是指在一个线程访问资源时,别的线程是无法访问这个资源的。

MainThread和WorkerThread

Android中可以将线程分为:MainThread和WorkerThread两大类

MainThread就是主线程,又称为UI线程,所有和UI相关的代码,都是运行在MainThread中的。

除了MainThread之外的线程,都是WorkerThread,原则上来讲WorkerThread是不允许操作UI组件的。

Android当中线程的使用

实现一个demo,要求实现点击按钮5秒钟之后,改变TextView的文字。

package cn.lixyz.handlertest;

import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends Activity { private TextView textView;
private Button button; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.text);
button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(){
@Override
public void run() {
super.run();
try {
sleep(5000);
textView.setText("改变之后的文字");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
});
}
}

MainActivity.java

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="@string/hello_world"
android:textSize="50dp" /> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="点击我改变文字" /> </LinearLayout>

activity_main.xml

像上面一样编码的话,点击按钮5秒之后,会提示错误:

并抛出异常:

09-15 03:28:33.964    5854-6002/cn.lixyz.handlertest E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-112
Process: cn.lixyz.handlertest, PID: 5854
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6024)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:820)
......

上面的代码和异常证明了,Android是不允许非UI线程去修改UI组件的。

但是也有例外,譬如ProgressBar,看代码

package cn.lixyz.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView; public class MainActivity extends Activity { private ProgressBar progressBar;
private Button button; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); progressBar = (ProgressBar) findViewById(R.id.progressBar);
button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
super.run();
for (int i = 0; i < 100; i++) {
try {
sleep(100);
progressBar.setProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}.start();
}
});
}
}

MainActivity.java

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <ProgressBar
android:id="@+id/progressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp" /> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="点击开始加载" /> </LinearLayout>

activity_main.xml

运行结果:

所以说:大多数情况下,在WorkerThread中是无法修改UI的,只有少数情况下才可以。

那么可以不可以把所有修改UI的代码全部放在MainThread中执行呢?答案是否定的。

在一个应用程序之中,主线程通常用于接收用户的输入,以及将运算的结果反馈给用户,后台运行耗时代码则会导致主线程阻塞,程序无法相应,也就是常见的ANR(application not responding),应用程序没有相应。

所以说,对于一些可能产生阻塞的操作,必须放到WorkerThread中,这时候就产生了WorkerThread和MainThread的通信问题。

Android笔记(二十九) Android中的异步更新(一) Android中的线程的更多相关文章

  1. Android笔记(十九) Android中的Fragment

    通常我们使用Activity来展示界面,但是在手机上界面可能显示的很好看,但在平板上,因为平板的屏幕非常大,手机的界面放在平板上可能会出现控件被拉长.控件之间间距变大等问题.为了更好的体验效果,在Ac ...

  2. Android笔记二十四.Android基于回调的事件处理机制

        假设说事件监听机制是一种托付式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器全然消失了,当用户在GUI控件上激发某个事件时,控 ...

  3. Android笔记(六十九) 仿微信界面(一)

          综合之前的Fragment和自定义组件的知识,实现微信界面 MainActivity.java package cn.lixyz.test; import android.app.Acti ...

  4. angular学习笔记(二十九)-$q服务

    angular中的$q是用来处理异步的(主要当然是http交互啦~). $q采用的是promise式的异步编程.什么是promise异步编程呢? 异步编程最重要的核心就是回调,因为有回调函数,所以才构 ...

  5. Java学习笔记二十九:一个Java面向对象的小练习

    一个Java面向对象的小练习 一:项目需求与解决思路: 学习了这么长时间的面向对象,我们只是对面向对象有了一个简单的认识,我们现在来做一个小练习,这个例子可以使大家更好的掌握面向对象的特性: 1.人类 ...

  6. Java笔记(二十九)……网络编程

    概述 网络模型 网络通讯的要素 ip地址:网络中设备的标识符 端口:用于标识同一台设备上不同的进程,有效端口:0~65535,其中0~1024是系统使用端口或者保留端口 TCP与UDP UDP特点: ...

  7. [ExtJS5学习笔记]第二十九节 sencha ext js 5.1.0中动态更换皮肤主题

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/42016107 本文作者:sushengmiyan ------------------ ...

  8. 论文阅读笔记二十九:SSD: Single Shot MultiBox Detector(ECCV2016)

    论文源址:https://arxiv.org/abs/1512.02325 tensorflow代码:https://github.com/balancap/SSD-Tensorflow 摘要 SSD ...

  9. Python笔记(二十九)_模块

    模块 在Python中,一个.py文件就是一个模块 if __name__ == '__main__':所有模块都有一个 __name__ 属性,__name__ 的值取决于如何应用模块 run当前文 ...

  10. PHP学习笔记二十九【接口】

    <?php //定义接口 //接口可以定义属性,但必须是常量而且是public //接口的所有方法必须是public interface Iusb{ public function start( ...

随机推荐

  1. Python - Django - session 的基本使用

    urls.py: from django.conf.urls import url from app02 import views urlpatterns = [ # app02 url(r'^app ...

  2. vuex中mutations数据响应

    vuex中的mutation需遵守Vue的响应规则: 既然Vuex的store中的状态是响应式的,那么在我们变更状态时,监视状态的Vuex最好在state中初始化好所有的所需属性. 如果需要在对象上添 ...

  3. Excel对某一列的数据插入处理,域名得出IP

    早期都是通过Excel做数据统计,对某一列的数据插入处理. 代码功能是从A列纯域名,将域名转换为IP,从域名A列得到IP写到B列. 代码 #!/usr/bin/python #coding:utf-8 ...

  4. maven 中配置多个mirror的问题

    公司搭建的maven私服做镜像,有使用aliyun的镜像,还有其他地方的, 默认情况下配置多个mirror的情况下,只有第一个生效.那么我们可以将最后一个作为默认值,前面配置的使用环境变量动态切换. ...

  5. android基础---->数据保存到文件

    Android使用与其他平台类似的基于磁盘的文件系统(disk-based file systems).这篇博客将描述如何在Android文件系统上使用File的读写APIs对Andorid的file ...

  6. linux中matlab的中文乱码问题

    ref:http://hi.baidu.com/36470902/item/47f3b133c419d989f5e4ade1 将系统的jre拷贝到matlab去 . sudo mv $MATLAB/s ...

  7. [转帖]Linux下主机间文件传输命令

    Linux下主机间文件传输命令 https://yq.aliyun.com/articles/53631?spm=a2c4e.11155435.0.0.580ce8ef4Q9uzs   SCP命令: ...

  8. 通俗理解TCP的三次握手

    三次握手流程的本质,可以这么理解:TCP的三次握手其实是双方各一次握手,各一次确认,只是其中一次握手和确认合并在一起. 当然也可以更通俗的去理解: "喂,你听得到吗?" " ...

  9. Mysql 定时备份(mysqldump)

    #!/bin/bash today=`date +%Y-%m-%d` deleday=`date -d '7 day ago' +%Y-%m-%d` path=/home/data/mysqlback ...

  10. WUSTOJ 1347: GCD(Java)互质

    题目链接:1347: GCD Description 已知gcd(a,b)表示a,b的最大公约数. 现在给你一个整数n,你的任务是在区间[1,n)里面找到一个最大的x,使得gcd(x,n)等于1. I ...