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 判断文件是否存在和删除文件的api (其中判断文件在不在让想起这个可以强兼容jenkins工作目录那个问题)

    判断文件在不在的api: os即operating system(操作系统),Python 的 os 模块封装了常见的文件和目录操作. os.path模块主要用于文件的属性获取,exists是“存在” ...

  2. 使用Commons math做数值计算

    使用Commons math做数值计算 觉得有用的话,欢迎一起讨论相互学习~Follow Me 最近使用jmetal做多目标的时候,想用一些简单的方法求最大值最小值方差和协方差矩阵,但是原生代码真的是 ...

  3. WebSocket接收音频,并推送到声卡上

    使用信息 import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableM ...

  4. redis八大应用场景

    1.缓存 缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力.Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓 ...

  5. 【Leetcode_easy】832. Flipping an Image

    problem 832. Flipping an Image solution1: class Solution { public: vector<vector<int>> f ...

  6. 雨幕——RainCurtian

    今天19年10月14日,也不算是个什么特别的日子.不多能让我的这一天变得特殊的,或许就是在今天我开通了我的第一个博客吧.细想过来每一天都是那么的相似,不过是因为有了某些事情,才变得特殊起来,比如新生命 ...

  7. 常见问题:MySQL/索引

    普通索引 最常用,没有任何限制. 唯一索引 必须唯一,但允许空值,如果是组合索引,列值的组合必须唯一. 组合索引 由于MySQL查询时,只能使用一个索引,因此建立组合索引在组合查询的场景下更加有效.组 ...

  8. ubuntu18.10 安装nodejs

    进入官网下载页面 下载对应版本 2.解压tar.xz文件在linux下,大部分情况下不能直接解压tar.xz的文件. 需要用 xz -d xxx.tar.xz 将 xxx.tar.xz解压成 xxx. ...

  9. [C#] - 从 HTML 代码中 转换 / 提取 可读文字(PlainText)的方法

    背景 在做网页数据分析的时候,我们关注的部分是内容,可以过滤掉HTML标签.Javascript.CSS等代码. 目标输入 <b>Hello World.</b><br/ ...

  10. Python 模块初始化的时候,发生了什么?

    假设有一个 hello.py 的模块,当我们从别的模块调用 hello.py 的时候,会发生什么呢? 方便起见,我们之间在 hello.py 的目录下使用 ipython 导入了. hello.py ...