目录
1. 什么是进程,什么是线程,两者有何区别
答:进程是cpu资源分配的最小单位。线程是cpu执行调度的最小单位。进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源;一个进程内可拥有多个线程,进程可开启进程,也可开启线程;一个线程只能属于一个进程,线程可直接使用同进程的资源,线程依赖于进程而存在。
详细的说明转自 aaronthon博客,内容见下?
什么是进程?什么是线程?
进程是系统中正在运行的一个程序,程序一旦运行就是进程。进程是系统资源分配的独立实体,每个进程都拥有独立的地址空间。一个进程无法访问另一个进程的变量和数据结构,如果想让一个进程访问另一个进程的资源,需要使用进程间通信,比如管道,文件,套接字等。
一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间。线程与进程的一个主要区别是,统一进程内的一个主要区别是,同一进程内的多个线程会共享部分状态,多个线程可以读写同一块内存(一个进程无法直接访问另一进程的内存)。同时,每个线程还拥有自己的寄存器和栈,其他线程可以读写这些栈内存。
线程是进程的一个实体,是进程的一条执行路径。当一个线程修改了进程的资源,它的兄弟线程可以立即看到这种变化。
进程和线程的区别体现在以下几个方面:
1.地址空间和其他资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其他进程内不可见。
2.通信:进程间通信IPC(管道,信号量,共享内存,消息队列),线程间可以直接独写进程数据段(如全局变量)来进程通信—— 需要进程同步和互斥手段的辅助,以保证数据的一致性。
3.调度和切换:线程上下文切换比进程上下文切换快得多。
4.在多线程OS中,进程不是一个可执行的实体。
进程和线程的选择取决以下几点:
1.需要频繁创建销毁的优先使用线程;因为对进程来说创建和销毁一个进程的代价是很大的。
2.线程的切换速度快,所以在需要大量计算,切换频繁时使用线程,还有耗时的操作时用使用线程可提高应用程序的响应。
3.因为对CPU系统的效率使用上线程更占优势,所以可能要发展到多机分布的用进程,多核分布用线程。
4.并行操作时用线程,如C/S架构的服务器端并发线程响应用户的请求。
5.需要更稳定安全时,适合选择进程;需要速度时,选择线程更好。
2. 线程生命周期
- 新建状态 New status : 创建Thread类的对象且还未调用start()方法,线程进入新建状态,这时不认为这线程是活动的状态
- 就绪状态 Runnable status : 线程进入就绪状态的几种方式:1. 线程在新建状态中调用start()方法进入就绪状态;2. 线程在运行状态失去CPU资源从而回到就绪状态;3. 线程从阻塞或等待状态上回到就绪状态。处于就绪状态的线程是活动的线程。
- 运行状态 Running status : 线程在就绪状态上获得CPU资源,执行run()。
- 阻塞状态/等待状态 Blocked/Waiting status : 处于运行状态的线程通过调用sleep() | wait() | Input/Output请求 | 同步锁状态 进入阻塞/等待状态。
- 死亡状态 Dead status : 当线程成功的执行完run()方法后进入死亡状态,这时线程不是活的,所以这时你调用start()方法就会跳java.lang.IllegalThreadStateException异常
2.1 Android 主线程与子线程概念理解
在 Android 中,一个进程默认只有一个线程,这个就是我们的主线程,主要负责处理 UI 的工作,以及通过 UI 界面与用户进行交互,所以当主线程卡顿的时候,就会呈现给用户界面卡顿的情况,从而用户觉得 APP 反应迟钝很“卡”。所以为了防止出现这种情况,我们开发者应该保证主线程在任何时候都保持着较高的响应速度,即主线程不能做任何耗时的操作(如:网络请求、I/0操作、数据库读写等),这些耗时的操作需要新建一个线程,即子线程(也叫工作线程)中去处理。
3. Java 多线程实例Demo
Java实现多线程的方法,创建线程类的方法有两种:一继承Thread类来,二实现Runnable接口。
3.1 继承Thread
public class MyThread extends Thread {
public void run() {
System.out.println("MyThread run..");
}
}
public class ThreadTest {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
3.2 实现Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
//放业务逻辑
System.out.println("MyRunnable run..,");
}
}
public class MyRunnableTest {
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
4. Android 多线程实现
子线程不可处理 UI 工作, 任何 UI 工作都需在主线程上处理。
4.1 Handler实现
利用Handler来实现子线程更新UI工作,
具体代码见下:
public class HandlerAddThread extends AppCompatActivity {
private TextView mDisplayTv;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_add_thread);
Button mClickBtn = findViewById(R.id.click_btn);
mDisplayTv = findViewById(R.id.display_tv);
//mHandler 用于处理主线程消息队列中的子线程消息
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
//更新 UI
mDisplayTv.setText("Jere test: User Handler ");
}
}
};
mClickBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//开启子线程,子线程处理 UI 工作
CustomChildThread customThread = new CustomChildThread();
customThread.start();
}
});
}
public class CustomChildThread extends Thread {
@Override
public void run() {
//在子线程中创建一个消息对象
Message childThreadMessage = new Message();
childThreadMessage.what = 1;
//将该消息放入主线程的消息队列中
mHandler.sendMessage(childThreadMessage);
}
}
}
4.2 HandlerThread实现
将工作线程的执行结果传递给主线程,从而在主线程中执行相关的 UI 操作,实现工作线程与主线程之间的通信。
Demo例子:利用HandlerThread来实现Progress bar加载,如下图所示?(按消息队列顺序先后执行:Start Progress Bar 1 -> Start Progress Bar 2 -> Start Progress Bar 1 )
详细代码:
public class HandlerThreadActivity extends AppCompatActivity {
private final int SET_PROGRESS_BAR_1 = 1;
private final int SET_PROGRESS_BAR_2 = 2;
private HandlerThread myHandlerThread;
private Handler mWorkHandler, mMainHandler;
private ProgressBar progressBar1, progressBar2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread);
TextView titleTv = findViewById(R.id.title_tv);
titleTv.setText("HandlerThread");
progressBar1 = findViewById(R.id.progress_bar_1);
progressBar2 = findViewById(R.id.progress_bar_2);
Button startBtn1 = findViewById(R.id.start_progress_bar_1_btn);
Button startBtn2 = findViewById(R.id.start_progress_bar_2_btn);
//创建HandlerThread对象
myHandlerThread = new HandlerThread("myHandlerThread");
//启动线程
myHandlerThread.start();
//创建Handler关联主线程,在主线程上执行run(),可以用于执行UI工作
mMainHandler = new Handler(getMainLooper());
//创建工作线程Handler,关联HandlerThread的Looper对象,重写handleMessage()方法,处理消息
mWorkHandler = new Handler(myHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SET_PROGRESS_BAR_1:
//设置Progress Bar 1
for (int i = 1; i <= 4; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
final int progressSchedule = i;
mMainHandler.post(new Runnable() {
@Override
public void run() {
progressBar1.setProgress(progressSchedule);
}
});
}
break;
case SET_PROGRESS_BAR_2:
//设置Progress Bar 2
for (int i = 1; i <= 4; i++) {
try {
Thread.sleep(1300);
} catch (InterruptedException e) {
e.printStackTrace();
}
final int progressSchedule2 = i;
mMainHandler.post(new Runnable() {
@Override
public void run() {
progressBar2.setProgress(progressSchedule2);
}
});
}
break;
default:
break;
}
}
};
startBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//通过mWorkHandler发送处理 progress bar 1 的信息
Message msg = new Message();
msg.what = SET_PROGRESS_BAR_1;
mWorkHandler.sendMessage(msg);
}
});
startBtn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//通过mWorkHandler发送处理 progress bar 2 的信息
Message msg = new Message();
msg.what = SET_PROGRESS_BAR_2;
mWorkHandler.sendMessage(msg);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
myHandlerThread.quit();
}
}
4.3 AsyncTask实现
具体代码请看另一篇博客?Android 多线程之AsyncTask学习
4.4 IntentService实现Demo
具体请看另一篇博客?IntentService例子Demo