一、线程的概述
1.1 线程的了解
是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执 行多个线程,提升性能
1.2 并发和并行
- 并发:在同一时刻,有多个指令在单个CPU上交替执行
- 并行:在同一时刻,有多个指令在单个CPU同时进行
1.3 进程和线程
- 进程:是正在运行的程序
- 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
- 动态性:进程的实质 是程序的一次执行过程,进程是动态产生,动态消亡的
- 并发性:任何进程都可以同其他进程一起并发执行
- 线程:是进程中的单个顺序控制流,是一条执行路径
- 单线程:一个进程如果只有一条执行路径,则称为单线程程序
- 多线程:一个进程如果有多条执行路径,则称为多线程程序
1.4 实现多线程的方式一( 继承Thread)
方法名称 | 说明 |
void run() | 在线程开启后,此方法将被调用执行 |
void start() | 使此线程开始执行,Java虚拟机会调用run方法() |
实现步骤:
- 定义一个类MyThread继承Thread类
- 在MyThread类中重写run()方法
- 创建MyThread类的对象
- 启动线程
package cn.scy.thead;
/**
* @ClassName: MyThread.class
* @Description: 创建线程的第一种方法(继承 Thread)
* @Author: 喆
* @Date: 2022/6/14 15:13
* @Software: IntelliJ IDEA
**/
/*
实现步骤:
定义一个类MyThread继承Thread类
在MyThread类中重写run()方法
创建MyThread类的对象
启动线程
*/
// 定义一个类MyThread继承Thread类
public class MyThread extends Thread{
// 在MyThread类中重写run()方法
@Override
public void run() {
System.out.println("我是一个线程!!!!");
}
public static void main(String[] args) {
// 创建MyThread类的对象
MyThread myThread = new MyThread();
// 启动线程
myThread.start();
}
}
两个小问题?
- 为什么要重写run方法?
因为run方法用来封装被线程执行的代码
2.run()和start()方法的区别?
run():封装线程执行的代码,直接调用,相当于普通方法的调用
start():启动线程;然后由JVM调用此线程的run()方法
1.5 实现多线程的方式二(实现Runnable接口)
- Tehread构造方法
方法 | 说明 |
Thread(Runnable target) | 分配一个新的Thread对象 |
Thread(Runnable target, String name) | 分配一个新的Thread对象 |
- 实现步骤
- 定义一个类MyRunnable实现Runnable接口
- 在MyRunnable类重写run()方法
- 创建MyRunnable类的对象
- 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
- 启动线程
package cn.scy.thead1;
/**
* @ClassName: MyRunnable.class
* @Description:
* @Author: 喆
* @Date: 2022/6/14 15:35
* @Software: IntelliJ IDEA
**/
/*
实现步骤
定义一个类MyRunnable实现Runnable接口
在MyRunnable类重写run()方法
创建MyRunnable类的对象
创建Thread类的对象,把MyRunnable对象作为构造方法的参数
启动线程*/
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
测试类
package cn.scy.thead1;
/**
* @ClassName: MyRunnableDemo.class
* @Description:
* @Author: 喆
* @Date: 2022/6/14 15:36
* @Software: IntelliJ IDEA
**/
public class MyRunnableDemo {
public static void main(String[] args) {
// 创建MyRunnable类的对象
MyRunnable myRunnable = new MyRunnable();
// 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
Thread thread = new Thread(myRunnable);
Thread thread1 = new Thread(myRunnable, "效力");
// 启动线程
thread.start();
thread1.start();
}
}
1.6 实现多线程方式三(实现Callable接口)
- 方法介绍
方法名 | 说明 |
V call() | 计算结果,如果无法计算结果,则抛出一个异常 |
FutureTask(Callable callable) | 创建一个 FutureTask,一旦运行就执行给定的 Callable |
V get() | 如有必要,等待计算完成,然后获取其结果 |
- 实现步骤
- 定义一个类MyCallable实现Callable接口
- Callable接口 在MyCallable类中重写call()方法
- 创建MyCallable类的对象
- 创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
- 创建Thread类的对象,把FutureTask对象作为构造方法的参数
- 启动线程
- 再调用get方法,就可以获取线程结束之后的结果。
package cn.scy.thread2;
import java.util.concurrent.Callable;
/**
* @ClassName: MyCallable.class
* @Description:
* @Author: 喆
* @Date: 2022/6/14 16:08
* @Software: IntelliJ IDEA
**/
// 定义一个类MyCallable实现Callable接口
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println("跟那个女孩表白" + i);
}
// 返回值就表示线程运行完毕之后的结果
return "答应";
}
}
测试类
package cn.scy.thread2;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
* @ClassName: Demo.class
* @Description:
* @Author: 喆
* @Date: 2022/6/14 16:12
* @Software: IntelliJ IDEA
**/
public class Demo {
public static void main(String[] args) throws Exception {
// 创建MyCallable类的对象
MyCallable myCallable = new MyCallable();
// 创建FutureTask的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
FutureTask<String> task = new FutureTask<>(myCallable);
// 创建Thread类的对象,把FutureTask对象作为构造方法的参数
Thread thread = new Thread(task);
String s = task.get();
// 启动线程
thread.start();
System.out.println(s);
}
}
三种实现方式的对比
- 实现Runnable、Callable接口
- 好处:扩展性强,实现该接口的同时还可以继承其他的类
- 缺点:: 编程相对复杂,不能直接使用Thread类中的方法
- 继承Thread类
- 好处:编程比较简单,可以直接使用Thread类中的方法
- 缺点:可以扩展性较差,不能再继承其他的类
1.7 设置和获取线程的名称
- 方法介绍
方法名 | 说明 |
void setName(String name) |
将此线程的名称更改为等于参数name |
String getName() | 返回此线程的名称 |
Thread c |