2020.5.31
多线程
- 什么是单线程,代码的执行路径只有一条路径。
- 缺点:有可能某个代码耗时时间长需要等待,其他程序不能进行,用户感觉差。
- 多线程:代码的执行路径有多条,这种执行环境称之为多线程环境。一般在支线程运行耗时代码。
线程的概述
- 线程依赖进程,没有进程也就谈不上线程。
- 进程开启之后就会执行很多任务,每个任务就是一个线程。
- 线程是CPU调度的基本单位。
- 我们Java编程,就是线程编写,因为虚拟机就是进程,不能在虚拟机里面运行进程。只能在虚拟机里面运行线程。
- 意义:多线程提高对CPU的使用率。
- 线程的调度是随机性的,没有规律。
进程
- 进程就是正在运行的应用程序。
- 计算机在同一时间点上,多个进程不是同时进行。同一个时间点上只能执行一个进程。感觉同时进行,因为(单核)CPU是在多个进程中高速切换,人的感官不会感觉出来。
- 开启一个进程,就是拥有资源。
并发和并行
- 并发:指的时多个任务,高速的交替执行。同一个实体上的多个事件。多台处理器上同时处理多个任务
- 并行:多个任务在同一时刻同时执行,不同实体上的多个事件。一台处理器上同时处理多个任务
java运行原理
- Java程序依靠虚拟机运行,虚拟机是一个进程,我们开启一个进程后,虚拟机就会调用主线程,所以我们编写的是多线程程序,Java是不能直接调用系统功能的,我们没法直接实现多线程,但是Java虚拟机可以直接调用C/C++写好的程序调用多线程,
- 因为CPU调度的基本单位是线程,在运行多线程程序时,单核CPU执行线程的方式是
怎么创建线程(线程开启的第一种方式)
- 我们可以通过Java提供的Thread类创建线程,和开启线程。
- 线程不要重复开启,重复开启会抛出异常。
- 线程调用start方法开启线程
- run()方法里面封装的是线程要执行的逻辑。
- 可以给线程起名和获取名字。
- 获取主线程的名字和修改名字。
- 多个线程就是并发执行。
- 多个线程的优先级设置。一般不设置,理论上说有效果。优先级高的抢占的概率高一些。
- 线程默认优先级是:5
- 线程的优先级最大是10
- 线程的优先级最小是1
线程的第二种开启方式
- 实现Runable接口,重写run方法,如果一个类继承了另一个类,要想创建多线程,就不能继承Thread类。Java提供了一个接口,实现了此接口就可以创建线程。
线程开启的第三种方法
- 实现Callable接口,重写call方法,执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。 FutureTask 是 Future 接口的实现类
- 特点是:当子线程执行结束之后,可以返回线程执行的结果。
- 创建的步骤:
- 创建一个类实现Callable 接口 重写接口中的call方法
- 创建一个FutureTask类将Callable接口的子类对象作为参数传进去
- 创建Thread类, 将FutureTask对象作为参数传进去
Runable/Callable的差别
- Runable:没有返回值,不能抛出异常,只能捕获处理
- Callable:有返回值,可以抛出异常。
代码
1.package org.westos.demo1;
/*Author:LH
CreatTime:2020.05.31.15:13*/
public class Test1 {
public static void main(String[] args) {
System.out.println("主线程前面代码");
System.out.println("主线程前面代码");
System.out.println("主线程前面代码");
MyThread myThread = new MyThread();
// 开启支线程,是创建支线程的实例对象并调用start()方法。
// 注意这里不是调run()方法,如果是调用此方法,就是普通的main()方法调用,还是主线程。
myThread.start();
for (int i = 0; i < 10; i++) {
System.out.println("A");
}
// 同一个支线程的实例对象不能被开启两次。否则会报错。
MyThread myThread1 = new MyThread();
myThread1.start();
for (int i = 0; i < 10; i++) {
System.out.println("主线程后面代码");
}
}
}
//创建分支线程,让一个类继承Thread,并重写run方法。run方法体内的代码就是支线程
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("B");
}
}
}
2.package org.westos.demo2;
/*Author:LH
CreatTime:2020.06.05.15:44*/
public class Test2 {
public static void main(String[] args) {
Mythread th1 = new Mythread("窗口1");
Mythread th2 = new Mythread("窗口2");
Mythread th3 = new Mythread("窗口3");
th1.start();
th2.start();
th3.start();
}
}
class Mythread extends Thread {
// 重写构造方法,将线程名称传入有参构造。
public Mythread(String name) {
super(name);
}
//将共享的数据变成静态变量。所有线程共同操作买100张票
static int num = 100;
@Override
public void run() {
while (num > 0) {
// 获取当前线程的名称
System.out.println(this.getName()+"卖出第" + (num--) + "