线程与进程、Android多线程编程
线程与进程、Android多线程编程
目录
- 一、概念
- 1.程序
- 2.进程
- 3.并发
- 4.并行
- 5.线程
- 二、Android中的进程与线程
- 1.安卓的进程
- 2.安卓的线程
- 三、Android多线程编程
- 1.线程的创建
- 1)继承Thread类
- 2)实现Runnable接口(常用)
- 2. 异步消息处理机制
- 1)Message
- 2)Handler
- 3)实战
一、概念
1.程序
程序是为了实现特定任务的一系列指令的有序集合,是存放在磁盘的可执行文件。它本身没有任何运行的含义,它只是一个静态的实体。
2.进程
进程是程序的一次执行过程,是一个动态的概念。
3.并发
并发是多个事件在同一时间间隔内发生。
并发是指一个处理器同时处理多个任务,在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
4.并行
并行是多个事件在同一时刻同时进行。
并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。作个比喻:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。
5.线程
线程是进程的一部分,描述指令流执行状态,它是进程中的指令执行流的最小单位。线程是进程中的一个实体,一个进程包括1 ~ n个线程。若把进程称为任务的话,那么线程则是任务中的一个子任务的执行。一个进程中可以有多个线程,他们可以并发的执行多个任务。
为啥会有线程这种东西?因为有并发进行并且共享数据的这种需求;虽然进程也可以满足这种需求,但是它的开销很大(创建进程,进程结束,进程切换… …)。而线程能减少并发执行的时间和空间开销。
总结:
程序是静态的,进程是动态的
程序 = 文件(静态的可执行文件)
进程 = 执行中的程序 = 程序 + 执行状态
并发是一个人做多件事,来回切换。
并行是多个人做多件事,互不干涉。
并发是轮流处理多个任务,并行是同时处理多个任务。
一个进程中可以同时存在多个线程,各个线程之间可以并发执行。
二、Android中的进程与线程
1.安卓的进程
Android中有五种进程:前台进程,可见进程,服务进程,后台进程,空进程。
详细介绍:https://blog.csdn.net/wolfking0608/article/details/83146268
2.安卓的线程
前面我们讲到,一个进程可以包含多个线程,因此进程和线程是包含与被包含的关系。简单情况下,一个进程可以只有一个线程, 即主线程。当一个应用程序启动之后,android系统会为这个应用程序创建一个主线程(Main Thread),它负责渲染视图,分发事件到响应监听器并执行,对界面进行轮询的监听,所以在Android里面主线程也叫UI线程,在UI线程里才能操作界面。
三、Android多线程编程
如果我们在UI线程中做一些比较耗时的操作,比如访问网络或者数据库,都可能阻塞UI线程。对于用户来说,APP看起来像是卡住了,更坏的情况是,如果UI线程阻塞时间太长(超过5秒),Android系统会弹出ANR(application not responding)错误提示框。所以为了确保用户体验,主线程必须确保其响应速度,任何时候我们都不应该在主线程中处理非常耗时的任务,而子线程的作用就是完成耗时的操作,确保主线程的响应速度。
下面就让我们从线程的基本用法开始学起吧。
1.线程的创建
1)继承Thread类
class MyThread extends Thread{@Overridepublic void run(){//线程行为}}//MyThread mt=new MyThread();//mt.start();new MyThread().start(); // 启动子线程,写在主线程中
步骤:
1、定义一个类继承Thread类,并重写Thread类的run()方法,run()方法的方法体就是线程要完成的任务;
2、创建该类的实例对象,即创建了线程对象;
3、调用线程对象的start()方法来启动线程,这样run()方法中的代码就会在子线程当中运行了。
注意,不是调用run()方法启动线程,run方法中只是定义需要执行的任务,如果调用run方法,即相当于在主线程中执行run方法,跟普通的方法调用没有任何区别,此时并不会创建一个新的线程来执行定义的任务。
下面我们通过一个java例子更好地了解一下这种创建线程的方法吧
public class ThreadDemo1 {public static void main(String args[]) { //执行main方法的线程就是主线程Thread t = new MyThread (); // 实例化出一个线程对象t.start();}
}// 继承Thread类
class MyThread extends Thread {public void run() {System.out.println("创建了一个新的线程");}
}
2)实现Runnable接口(常用)
上一个方法虽然代码简单,但有很大的缺点,继承Thread类后就不能再继承别的类了,所以在开发中,优先选择实现Runable接口的方式。实现的方式没有类的单继承性的局限性,且更适合用来处理多个线程有共享数据的情况。
class MyThread implements Runnable {@Overridepublic void run() {//处理具体的逻辑}
}
MyThread myThread = new MyThread();
new Thread(myThread).start();
步骤:
1、定义一个类实现Runnable接口;
2、创建该类的实例对象obj;
3、将obj作为构造函数参数传入Thread类实例对象,这个对象才是真正的线程对象;
4、调用线程对象的start()方法启动该线程。
同样来看个简单的java例子吧
public class ThreadDemo2 {public static void main(String args[]) {MyThread mt = new MyThread();// mt.start(); //会报错,任务类MyThread中没有start()方法// mt.run(); // 仅仅在主线程调用任务类MyThread中的run()方法,并没有新开一个线程Thread t = new Thread(mt); // 传入任务类MyThread对象,实例化出一个线程对象t.start(); // 调用线程对象的start()方法}
}//创建任务类,实现Runnable接口
class MyThread implements Runnable {public void run() {System.out.println("创建了一个新的线程");}
}
如果不想专门再定义一个类去实现Runnable接口,也可以使用匿名类的方式,这种写法更为常见
new Thread(new Runnable() {@Overridepublic void run() {// 处理具体的逻辑}
}).start();
2. 异步消息处理机制
现在我们都知道,耗时操作可以另外创建一个线程来运行以避免堵塞主线程。还有Android不允许在子线程中进行UI操作,因为Android的UI是线程不安全的(具体的原因和实践我在这里就不解释和进行了,想了解的可以上网查或看《第一行代码》)。但是有些时候,我们必须在子线程里去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件,这该如何是好呢?
对于这种情况,Android提供了一套异步消息处理机制,完美地解决了这个问题,可以从子线程回到主线程中执行并带回结果。
Android中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper。 这里我主要介绍Message和Handler,其余的大家可以参考《第一行代码》进行学习。
1)Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。
2)Handler
Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler的handleMessage()方法中。Handler是主线程与子线程的通信媒介。
3)实战
现在我们通过一个具体的例子来实践一下如何使用Message和Handler。新建一个ThreadTest项目,然后修改activity_main.xml中的代码,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/change_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Change text" /><TextViewandroid:id="@+id/text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"android:textSize="30sp"/></LinearLayout>
布局文件中定义了两个控件,Button用于改变TextView中显示的内容,我们希望在点击Button后可以把TextView中显示的字符串改成Nice to meet you。
接着我们来修改MainActivity中的代码,如下所示:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{private TextView text;private static final int UPDATE_TEXT = 1; // 定义了一个整型常量 UPDATE_TEXT,用于表示更新TextView这个动作@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);text = findViewById(R.id.text);Button changeText = findViewById(R.id.change_text);changeText.setOnClickListener(this);}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.change_text:// 开启了一个子线程new Thread(new Runnable() {@Overridepublic void run() {/* 创建了一个Message(android.os.Message)对象,并将它的what字段的值指定为UPDATE_TEXT,然后调用Handler的sendMessage()方法将这条Message发送出去*/Message message = new Message();message.what = UPDATE_TEXT;handler.sendMessage(message);}}).start();break;default:break;}}// 新增一个Handler对象,并重写父类的handleMessage()方法,在这里对具体的Message进行处理。// 使用new handler()来实例化可能会出现警告,在参数中传入Looper.getMainLooper()可以确保Handler是在主线程中private Handler handler = new Handler(Looper.getMainLooper()) {public void handleMessage(Message message) {/* Handler收到Message,并在handleMessage()方法中对它进行处理。注意此时handleMessage()方法中的代码就是在主线程当中运行的了,所以我们可以在这里进行UI操作*/switch (message.what) {case UPDATE_TEXT:// 如果发现Message的what字段的值等于UPDATE_TEXT,就将TextView显示的内容改成Nice to meet youtext.setText("Nice to meet you");break;default:break;}}};}
使用步骤:
1、在主线程中创建一个Handler对象,重写它的handleMessage方法
2、在子线程中创建Message对象
3、调用Handler对象的sendMessage()方法发送Message
这里仅仅是为了举个例子而已,并没有涉及耗时操作,在实际开发过程中,在子线程中会进行一些耗时操作,如网络连接,下载文件,数据库操作等,然后根据这些耗时操作得到的结果来更新UI。
好啦,要讲的内容就那么多了,上面这些内容其实是Android 四大组件中服务的基础。Android/Java提供了很多类/接口来帮助大家完成异步操作,runOnUiThread()方法,AsyncTask抽象类也都常见于Android多线程编程,这些就留着让你们自己去探索啦!
参考资料:
Android进程与线程基本知识
Activity runOnUiThread() 方法使用
Android中AsyncTask的简单用法
线程与进程、Android多线程编程相关推荐
- Android多线程编程(一)- 线程基础
Android多线程编程(一) 到了学习下一部分了,多线程编程一直都是Android经常使用的部份,在进行网络请求或者访问数据库时,为了避免主线程被耗时操作阻塞了进度,通常都会开启子线程进行处理,多线 ...
- android: 多线程编程基础
9.1 服务是什么 服务(Service)是 Android 中实现程序后台运行的解决方案,它非常适合用于去执行那 些不需要和用户交互而且还要求长期运行的任务.服务的运行不依赖于任何用户界面,即使 ...
- android 多线程编程
主线程的职责是创建.显示和更新UI控件.处理UI事件.启动子线程.停止子线程;子线程的职责是进行处理和向主线程发出更新UI消息,而不是直接更新UI. android 多线程编程报错: 05-14 15 ...
- Android开发实例——倒计时器——Android多线程编程
文章目录 一.倒计时器功能描述 二.实现步骤 1.新建Activity,命名为ThreadDemo 2.设计ThreadDemo 的布局文件 3.编写ThreadDemo.java 文件代码 3.1 ...
- Android多线程编程
Android多线程编程 其实就是将耗时操作放在子线程里运行,防止主线程被阻塞,影响软件使用. 线程的基本用法 定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面编 ...
- linux查询某域线程是否满了,Linux多线程编程的时候怎么查看一个进程中的某个线程是否存活...
pthread_kill: 别被名字吓到,pthread_kill可不是kill,而是向线程发送signal.还记得signal吗,大部分signal的默认动作是终止进程的运行,所以,我们才要用sig ...
- 进程、线程及python的多线程编程
目录 一.进程.线程和并行执行 1.什么是进程.线程 注意 2.什么是并行执行 二.python的多线程编程 threading模块 语法 多线程编程的传参 演示 三.总结 一.进程.线程和并行执行 ...
- 线程、进程、多线程、多进程和多任务有啥关系?
点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取后台回复"k8s",可领取k8s资料 可能学习操作系统开 ...
- 线程、进程、多线程、多进程 和 多任务 小结
目录 1 进程 2 线程 3 多进程 4 多线程 5 线程与进程的关系 6 线程和进程的区别 7 进程的优缺点 7.1 进程的优点 7.2 进程的缺点 8 线程的优缺点 8.1 线程的优点 8.2 线 ...
最新文章
- (转载)人人都会OSGI--实例讲解OSGI开发
- Tomcat Filter 自己动手实现
- 「Vueconf」探索 Vue3 中 的 JSX
- OpenCV显示中文汉字,未使用CvxText和FreeType库
- YUI3下widget的plugin开发
- Java web 第一天
- gis投影中未定义的地理转换_PhotoScan中经纬度转换为投影坐标快捷方法
- iis启动服务时提示在本地计算机 无法启动iis admin服务,iis 依存服务和组没法启动...
- arpu计算方法、pv、uv、ip的意思
- 英语四级和计算机一级算多少学分,英语四级成绩怎么算分 多少分合格
- Chrome下载文件,文件名出现乱码解决
- java动物继承_java 编码实现动物世界的继承关系:动物(Animal)属性:名称(name)具有行为:吃(eat)、睡觉(sleep)...
- 定时开关机实现原理-Android4.4/6.0
- java实训第二次作业//181021(个人所得税计算器;判断闰年与平年;个人作业展示系统(方法调用))
- 缺芯导致全球汽车减产超一千万辆
- xhci键盘linux,QEMU “vmstate_xhci_event” 漏洞
- datastage 函数_DataStage常用函数大全.doc
- Iterm2保存服务器账密
- 关于电磁转矩这篇文章不错
- Android QQ空间浏览图片动画特效的实现(※)