一、线程和进程概念
线程是程序执行的最小单元,属于进程的一个实体。一个进程包含多个线程,线程共享的资源有内存空间、文件句柄。
线程特性:
- 轻量级:线程的开销相比进程小很多,线程仅需要少量资源就行。
- 并发执行:多个线程可以同时间并发执行,线程之间互不干扰。
- 共享资源: 同一进程的线程共享线程资源,多个进程可以同时访问进程的全局变量。
进程和线程的区别:
进程是程序的一次执行过程,资源分配的最小单位,进程之间通信复杂;线程是进程一个执行单位,程序执行流的最小单位,进程之间通信简单。
线程的生命周期:
- New状态:
//创建线程对象,未启动,线程没有执行任务代码
Thread t = new Thread(()->{
while(true){
System.out.println("hello thread");
try{
Thread.sleep(1000);
}catch(InterruptedException){
throw new RuntimeException(e);
}
}
});
- Runable状态:
调用线程的start()方法,线程从新建状态转变为就绪状态,具备执行条件。
Thread thread = new Thread(() -> {
System.out.println("线程正在执行");
});
thread.start();
调用start()方法之后,不会立即执行,线程进行就绪状态,等待调度的阶段。
Blocked状态:
执行过程因为一些因素,无法继续执行,进入阻塞状态,阻塞状态不占用CPU,解决阻塞问题之后,线程才会进入Runable状态Waiting状态:
线程进入等待状态,需要被显式唤醒才能继续执行Terminated状态:
执行完run()或者因为异常,线程提前终止,线程进入死亡状态,处于这个状态的线程无法重启,会被JVM回收。
二、创建多线程的五种方式
1、实现Runable接口:
- 实现Runable接口中的run()方法,使用Thread类构造函数传入Runable对象,调用start()方法启动线程。
Thred t = new Thred(new MyRunable());
t.start();
2、继承Thred类:
继承Thred类并重写run()方法,创建Thred子类对象并调用start()启动线程。
MyThread t = new MyThread();
t.start();
3、使用Callable和FutureTask
实现Callable接口的call()方法,使用FutureTak包装Callable对象
FutureTask<Integer> task = new FutureTask<>(new MyCallable());
Thread thread = new Thread(task);
thread.start();
4、线程池
通过ExecutorService提交Runable或Callable,不直接创建和管理线程,适合大量并发任务。
ExecutorService excutor = Executors.newFixedThredPool((10));
executor.submit(new MyRunable());
5、CompletableFuture
本质也是线程池,Java8引入的,方便进行异步任务调用,通过多种方法轻松处理异步任务之间的依赖关系.
CompletableFuture<Void> future1 = ComletabbleFuture.runAsync(()->{});