线程的基本认识
什么是线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
为什么要用多线程
- 在多核CPU中,利用多线程可以实现真正意义上的并行;
- 根据线程本身的异步执行特性,来提升程序运行的效率。
应用场景
- 使用多线程实现文件下载;
- 后台任务:如定时向大量(100W以上)的用户发送邮件;
- 异步处理:记录日志;
- 多步骤的任务处理,可根据步骤特征选用不同个数和特征的线程来协作处理,多任务分割,有一个主线程分割给多个线程完成。
如何在Java中应用多线程
- 继承Thread类,重写run()方法。
package com.wxw;
public class ThreadDemo extends Thread {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo();
// 启动线程
threadDemo.start();
}
}
- 实现Runnable接口,实现run()方法。
package com.wxw;
public class RunnableDemo implements Runnable {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
RunnableDemo runnableDemo = new RunnableDemo();
Thread thread = new Thread(runnableDemo);
thread.start();
}
}
- 实现Callable接口,实现call()方法。该方式可以接收返回值。
package com.wxw;
import java.util.concurrent.*;
public class CallableDemo implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("当前线程:" + Thread.currentThread().getName());
Thread.sleep(3000);
return "Hello Mic";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 使用FutureTask进行包装
FutureTask<String> futureTask = new FutureTask<String>(new CallableDemo());
// FutureTask实现了Runnable接口与Future,所以可以使用Thread进行封装
Thread thread = new Thread(futureTask);
thread.start();
// 调用get()方法时会阻塞线程
String result = futureTask.get();
System.out.println(result);
}
}
线程的生命周期
Java线程从创建到销毁,一共经历6个状态:
1. NEW:初始状态,线程被构建,但是还没有被调用start方法
2. RUNNABLED:运行状态,Java线程把操作系统中的就绪和运行两种状态统一称为“运行中”
3. BLOCKED:阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了CPU使用权,阻塞状态也分为几种情况
4. WAITING:等待状态
5. TIME_WAITING:超时等待状态,超时以后自动返回
6. TERMINATED(terminated泰美雷特):终止状态,表示当前线程执行完毕