1 线程概述
- 线程的核心问题是线程提供了并行解决方案
2 线程的相关概念
2.1 进程
进程(Process)是计算机中的程序关于某数据集合上的一次运动活动,是操作系统进行资源分配与调度的基本单位。可以把进程简单的理解为正在操作系统中运行的一个程序
2.2 线程
1 线程(Thread)是进程的一个执行单元。一个线程就是进程中一个单一顺序的控制流,是进程的一个执行分支。
2 进程是线程的容器,一个进程至少有一个线程,当一个进程中没有线程时,这个进程就结束了。
3 在操作系统中是以进程为单位分配资源。每个线程都有各自的线程栈,自己的寄存器环境,自己的线程本地存储。
4 主线程与子线程:JVM启动时会创建一个主线程,该主线程负责执行main方法。主线程就是运行main方法的线程。Java中的线程是不孤立的,线程之间存在一些联系。如果A线程中创建了B线程,称B线程为A线程的子线程,相应的A线程是B线程的父线程。
2.3 串行、并发、并行
2.3.1串行(Sequential)
一个挨着一个顺序执行,前面的执行完毕后,再执行后面的。效率低。
2.3.2 并发(Concurrent)
一段时间内多个任务都在运行。效率高。
2.3.3 并行(Parallel)
多个任务同时开始,是并发的特殊情况。效率高。
如下图:
image.png
3 创建线程的方法
- 方法1:继承Thread类
- 方法2:实现Runnable接口
- 方法3:实现Callable接口
- 方法4:使用线程池创建线程
3.1 继承Thread类创建线程
//1:定义类继承 Thread
public class Thread01 extends Thread{
//2:重写 Thread 父类中的 run()
@Override
public void run() {
System.out.println("子线程");
}
public static void main(String[] args) {
//3)创建子线程对象
Thread01 t=new Thread01();
//4)启动线程
t.start();
System.out.println("主线程");
}
}
运行结果:
主线程
子线程
代码分析:
- 调用线程的start()方法来启动线程。启动线程的实质就是请求JVM运行相应的线程,这个线程具体什么时候运行由线程调度器(Scheduler)决定。
- start()方法的作用:启动子线程,启动成功的线程会自动调用run()方法。
- 如果开启了多个线程,start()调用的顺序并不一定就是线程启动的顺序,多线程运行结果与代码执行顺序或调用顺序无关。线程调用具有随机性
3.2 实现Runnable接口创建线程
如果线程类已经有父类,就不能使用继承Thread类来实现线程,此时可以实现Runnable接口来创建线程。
public class Thread03_1 implements Runnable{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("sub "+i);
}
}
public static void main(String[] args) {
Thread03_1 thread03_1 = new Thread03_1();
Thread thread = new Thread(thread03_1);
thread.start();
for (int i = 0; i <100 ; i++) {
System.out.println("main "+i);
}
}
}
3.3 实现Callable接口创建线程
Callable接口内只有一个call方法,所以是函数式接口,能返回线程执行结果,要抛异常,结合FutureTask类获取线程的返回值
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
for (int i = 0; i <5 ; i++) {
System.out.println("call i="+i);
}
return "callable";
}
}
public class CallableDemo {
public static void main(String[] args) {
//创建线程对象
MyThread myThread=new MyThread();
//将线程对象包装到futureTask中,线程返回Stirng类型的值
FutureTask<String> futureTask=new FutureTask<>(myThread);
Thread thread=new Thread(futureTask);
//启动线程
thread.start();
String result= null;
try {
//获取线程返回结果
result = (String) futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//输出返回结果
System.out.println(result);
}
}
运行结果:
call i=0
call i=1
call i=2
call i=3
call i=4
callable