Android 多线程之几个基本问题

Android中的进程和线程

  • Android中的一个应用程序一般就对应着一个进程,多进程的情况可以参考Android 多进程通信之几个基本问题
  • Android中更常见的是多线程的情况,一个应用程序中一般都有包括UI线程等多个线程。Android中规定网络访问必须在子线程中进行,而操作更新UI则只能在UI线程。
  • 常见的网络请求库,如OkHttp、Volly等都为我们封装好了线程池,所以我们在进行网络请求时一般不是很能直观地感受到创建线程以及切换线程的过程。
  • 线程是一种很宝贵的资源,要避免频繁创建销毁线程,一般推荐用线程池来管理线程。

线程的状态

线程可能存在6种不同的状态:新创建(New)、可运行(Runnable)、阻塞状态(Blocked)、等待状态(Waiting)、限期等待(Timed Waiting)、终止状态(Terminated)

  • 新创建(New):创建后但还未启动的线程(还没有调用start方法)处于这种状态
  • 可运行(Runnable):一旦调用了start方法,线程就处于这种状态。需要注意的是此时线程可能正在执行,也可能在等待CPU分配执行的时间
  • 阻塞状态(Blocked):表示线程被锁阻塞,等待获取到一个排他锁。在程序等待进入同步区域时,线程将进入这种状态
  • 等待状态(Waiting):处于这种状态的线程不会被分配CPU执行时间,它们要等待被其他线程显示地唤醒。调用以下方法会让线程进入这种状态:

    • 没有设置Timeout参数的Object.wait()方法
    • 没有设置Timeout参数的Thread.join()方法
  • 限期等待(Timed Waiting):与等待状态(Waiting)不同的是,处于这种状态的线程不需要等待其它线程唤醒,在一定时间之后会由系统唤醒。调用以下方法会让线程进入这种状态:

    • Thread.sleep()方法
    • 设置了Timeout参数的Object.wait()方法
    • 设置了Timeout参数的Thread.join()方法
  • 终止状态(Terminated):表示线程已经执行完毕。导致线程终止有2种情况:

    • 线程的run方法执行完毕,正常退出
    • 因为一个没有捕获的异常而终止了run方法

创建线程

创建线程一般有如下几种方式:继承Thread类;实现Runnable接口;实现Callable接口

  • 继承Thread类,重写run方法
public class TestThread extends Thread {@Overridepublic void run() {System.out.println("Hello World");}public static void main(String[] args) {Thread mThread = new TestThread();mThread.start();}
}
  • 实现Runnable接口,并实现run方法
public class TestRunnable implements Runnable {@Overridepublic void run() {System.out.println("Hello World");}public static void main(String[] args) {TestRunnable mTestRunnable = new TestRunnable();Thread mThread = new Thread(mTestRunnable);mThread.start();}
}
  • 实现Callable接口,重写call方法

    • Callable可以在任务接受后提供一个返回值而Runnable不行
    • Callable的call方法可以抛出异常,Runnable的run方法不行
    • 运行Callable可以拿到一个Future对象,表示计算的结果,通过Future的get方法可以拿到异步计算的结果,不过当前线程会阻塞。
public class TestCallable {public static class MyTestCallable implements Callable<String> {@Overridepublic String call() throws Exception {//call方法可以提供返回值,而Runnable不行return "Hello World";}}public static void main(String[] args) {MyTestCallable myTestCallable = new MyTestCallable();//手动创建线程池ExecutorService executorService = new ThreadPoolExecutor(1,1,0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10));//运行callable可以拿到一个Future对象Future future = executorService.submit(myTestCallable);try {//等待线程结束,future.get()方法会使当前线程阻塞System.out.println(future.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
}
  • 以上三种方式就是常见的创建线程的方式。推荐使用实现Runnable接口的方法。

线程中断

  • 当一个线程调用interrupt方法时,线程的中断标识为将被设置成true
  • 通过Thread.currentThread().isInterrupted()方法可以判断线程是否应该被中断
  • 可以通过调用Thread.interrupted()对中断标志位进行复位(设置为false)
  • 如果一个线程处于阻塞状态,线程在检查中断标志位时如果发现中断标志位为true,则会在阻塞方法处抛出InterruptedException异常,并且在抛出异常前会将中断标志位复位,即重新设置为false
  • 不要在代码底层捕获InterruptedException异常后不做处理

同步的几种方法

同步的方式一般有如下3种:volatile关键字、synchronized关键字、重入锁ReentrantLock

volatile关键字
  • volatile关键字实现多线程安全关键在于它的可见性特性,但它需要满足一些条件才能保证线程安全,具体可以查看文章深入理解Java虚拟机(八)之Java内存模型
  • 在用volatile关键字来实现多线程安全时需要注意volatile不保证原子性,也就是不能用于一些自增、自减等操作,也不能用于一些不变式中,自增、自减比较好理解,下面看看不变式的情况
public class VolatileTest {private volatile int lower,upper;public int getLower() {return lower;}public void setLower(int value) {if (value > upper) {throw new IllegalArgumentException();}this.lower = value;}public int getUpper() {return upper;}public void setUpper(int value) {if (value < lower) {throw new IllegalArgumentException();}this.upper = value;}
}
  • 上面的例子中,如果初始值是(0,5),线程A调用setLower(4),线程B调用setUpper(3),显然最后结果就会变成(4,3)了
  • volatile使用的场景常见的有作为状态标志以及DCL单例模式
synchronized关键字和重入锁ReentrantLock
  • synchronized关键字比较常见,可以用于同步方法也可以用于同步代码块,一般推荐用同步方法,同步代码块的安全性不高。
  • 重入锁ReentrantLock相比synchronized提供了一些独有的特性:可以绑定多个解锁的条件Condition、可以实现公平锁、可以设置放弃等待获取锁的时间。
public class ReentrantLockTest {private Lock mLock = new ReentrantLock();//true,表示实现公平锁<!--private Lock mLock = new ReentrantLock(true);-->private Condition condition;private void thread1() throws InterruptedException{mLock.lock();try {condition = mLock.newCondition();condition.await();System.out.println("thread1:Hello World");}finally {mLock.unlock();}}private void thread2() throws InterruptedException{mLock.lock();try {System.out.println("thread2:Hello World");condition.signalAll();}finally {mLock.unlock();}}
}
  • 一个ReentrantLock有多个相关的Condition,调用Condition的await方法会让当前线程进入该条件的等待集并阻塞,直到另一个线程调用了同一个条件的signalAll方法激活因为这个条件而进入阻塞的所有线程
  • 一般线程同步用得比较多的还是synchronized同步方法和一些java.util.concurrent包提供的一些类

如何安全的终止线程

虽然我们一般都是利用线程池来管理线程而不会直接显示地创建线程,但是作为线程相关知识的一部分,我们还是要了解如何安全地终止一个线程。

要安全地终止一个线程,一般有2种方法:中断和标志位

(1)利用中断来终止线程

Thread thread = new Thread(new Runnable() {@Overridepublic void run() {while (!Thread.currentThread().isInterrupted()) {//do something}}
});//当我们调用Thread的interrupt方法时,线程就会退出循环停止了。
thread.interrupt();

(2)通过标志位

private static class MyRunnable implements Runnable {//控制线程的标志位,需要用 volatile关键字   private volatile boolean on = true;@Overridepublic void run() {while (on) {//do something }}public void cancel() {on = false;}
}//启动线程
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);//终止线程
myRunnable.cancel();

              欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!

AntDream

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/277193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web下的整体测试

随着Internet的日益普及&#xff0c;现在基于B/S结构的大型应用越来越多&#xff0c;可如何对这些应用进行测试成为日益迫切的问题。有许多测试人员来信问我B/S的测试如何做&#xff0c;由于工作较繁忙&#xff0c;对大家提出的问题也是头痛医头脚痛医脚&#xff0c;没有对WEB的…

用计算机算算术平方根顺序是ON然后是什么,第2课时用计算器求一个正数的算术平方根.ppt...

1.比较下列各组数的大小&#xff1a;(1) 与(2) 与 8依次按键显示&#xff1a;1.732 050 808例3 小丽想用一块面积为400 cm2的正方形纸片&#xff0c;沿着边的方向剪出一块面积为300 cm2的长方形纸片&#xff0c;使它的长宽之比为3:2&#xff0e;她不知能否裁得出来&#xff0c;…

MySQL 命令

版权声明&#xff1a;本文首发 http://asing1elife.com &#xff0c;转载请注明出处。 https://blog.csdn.net/asing1elife/article/details/82892834 MySQL 一些常见命令 更多精彩 更多技术博客&#xff0c;请移步 asing1elife’s blog 查看版本号 mysql -V重启/启动/停止 mys…

Bookshelf 2 简单DFS

链接&#xff1a;https://ac.nowcoder.com/acm/contest/993/C来源&#xff1a;牛客网 题目描述 Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly, and now the only available space is at the top.FJ…

一步一步SharePoint 2007之五:向网站中添加一个子网站

一步一步SharePoint 2007之五&#xff1a;向网站中添加一个子网站摘要感受完看到成果的激动&#xff0c;感受完邻家女孩的漂亮、可爱和端庄&#xff0c;不要停止&#xff0c;来&#xff0c;让我们一起来动手打造心目中的完美女神吧&#xff01;本篇文章将介绍如何向一个网站中添…

微型计算机系统分为哪几个层次,计算机系统分为哪4层?

满意答案al053192014.06.23采纳率&#xff1a;49% 等级&#xff1a;12已帮助&#xff1a;7516人第一层&#xff1a;物理层(PhysicalLayer)&#xff0c;规定通信设备的机械的、电气的、功能的和过程的特性&#xff0c;用以建立、维护和拆除物理链路连接。具体地讲&#xff0c…

ASP.NET Core 基础教程 - ASP.NET Core 基础教程 - 简单教程,简单编程

原文:ASP.NET Core 基础教程 - ASP.NET Core 基础教程 - 简单教程&#xff0c;简单编程 ASP.NET Core 是对 ASP.NET 有重大意义的一次重新设计。本章节我们将介绍 ASP.NET Core 中的一些新的概念和它们是如何帮助我们开发现代化的 Web 应用程序 尽管 ASP.NET Core 是跨平台的&a…

参数初始化

通过以下形式进行参数初始化 self.fc nn.Linear(n_head * d_v, d_model) nn.init.xavier_normal_(self.fc.weight) 转载于:https://www.cnblogs.com/yeran/p/11197047.html

使用input type=file 上传文件时需注意

在asp.net的中使用<input typefile />控件上传文件对文件的大小有限制,默认情况下大概在4m左右,如果上传再大的文件时就会出页面无法显示的错误.修改web.config文件中的参数可以设置该控件上传文件的大小,web.config中配置如下:在<system.web>节点下增加"<…

html模板 循环里if,django模板里循环变量table里想要两个一行如何控制

2016-8-3 周三做项目时遇到的问题&#xff1a;每个div由循环变量输出&#xff1a;{% for key,value in formextenddetail %}{{ key }}{{ value }}{% endfor %}但是我想两个div一行&#xff0c;使用...这种样子因为我负责的是前端&#xff0c;views这些不是很熟悉&#xff0c;想…

ASP.NET Core Windows 环境配置 - ASP.NET Core 基础教程 - 简单教程,简单编程

原文:ASP.NET Core Windows 环境配置 - ASP.NET Core 基础教程 - 简单教程&#xff0c;简单编程 ASP.NET Core Windows 环境配置 ASP.NET Core 是对 ASP.NET 有重大意义的一次重新设计。本章节我们将介绍 ASP.NET Core 中的一些新的概念和它们是如何帮助我们开发现代化的 Web 应…

Prim算法求最小生成树

给定一个n个点m条边的无向图&#xff0c;图中可能存在重边和自环&#xff0c;边权可能为负数。 求最小生成树的树边权重之和&#xff0c;如果最小生成树不存在则输出impossible。 给定一张边带权的无向图G(V, E)&#xff0c;其中V表示图中点的集合&#xff0c;E表示图中边的集合…

用installshield打包的asp.net程序

现在需要打包一个asp.net程序&#xff0c;具体要求如下&#xff1a;1、动态建立web虚拟目录或web站点&#xff0c;并保存至web.config文件相关字段中。2、动态建立ftp目录&#xff0c;并保存至web.config文件相关字段中。3、动态建立数据库联接类型sql或oracle&#xff0c;对sq…

合肥工业大学计算机学院王院长,王青山(合肥工业大学教授)_百度百科

王青山(合肥工业大学教授)语音编辑锁定讨论上传视频本词条缺少概述图&#xff0c;补充相关内容使词条更完整&#xff0c;还能快速升级&#xff0c;赶紧来编辑吧&#xff01;王青山&#xff0c;中国汉族人&#xff0c;合肥工业大学教授&#xff0c;现任中国计算机学会、ACM、IEE…

go 中gcc 编译问题(gcc.exe fatal error no input files compilation terminated)

2019独角兽企业重金招聘Python工程师标准>>> 问题背景 在windows 中编译 go 的pipe时由于pipe依赖sqlite&#xff0c;需要通过cgo进行编译。出现如下异常 gcc.exe fatal error no input files compilation terminated 问题分析 由于 windows中缺少c 的编译环境 解决…

35岁以前把下面十件事做好

35岁是青春的后期&#xff0c;35岁以后是收获的季节&#xff0c;如果你没有资格说这句话&#xff0c;你将会憎恨自己。所以在35岁以前&#xff0c;在烂漫蓬勃的青春年华里&#xff0c;你最好把下面十件事做好&#xff1a; 第一&#xff0c;学会本行业所需要的一切知识并有所发展…

XCode 10 升级问题总结

一、 library not found for -lstdc.6.0.9 xcode 10 中删除了内置 libstdc.6.0.9.tbd&#xff0c;工程中一些SDK依赖这个库&#xff0c;需要把xcode 9.4 的libstdc.6.0.9.tbd 添加到xcode中&#xff0c;重启xcode。 libstdc.6.0.9.tbd 的下载地址&#xff1a;libstdc.6.0.9 真机…

重心转移

做了好些时候的题了&#xff0c;发现做题对身体的摧残比普通的写代码还要重的多&#xff0c;为了我的眼睛&#xff0c;还是不要那么卖命的做ACM了&#xff0c;反正这个假期还算是比较有收获。而且&#xff0c;在没有指导老师的帮助下做难题&#xff0c;根本就是一条艰巨异常的路…

ArcEngine开发体验(附许可)

ArcGIS Engine Developer Guide ArcGIS9.0开发文档《Engine_Developers_Guide.pdf》376 &#xff0c;花了两三天看完了。guide特点&#xff1a;1 guide里面的基础性的东西很多&#xff0c;涉及com开发应用&#xff0c;开发语言&#xff0c;环境和ao架构介绍的内容2 介绍.net开发…

安装mysql-connector-python-8.0.11-py3.6遇到问题

1.提示“This application requires Visual Studio 2015 Redistributable” 下载vc_redist.x86安装即可。 下载链接&#xff1a;https://download.microsoft.com/download/6/D/F/6DF3FF94-F7F9-4F0B-838C-A328D1A7D0EE/vc_redist.x86.exe https://download.microsoft.com/downl…