学习内容来源于蚂蚁课堂,感谢蚂蚁课堂大佬的指导,本文仅供学习记录使用,如有不适,请联系作者。
一、线程与进程
应用程序:可执行软件,在应用系统中都会有一个进程,进程中有不同的执行路径(线程的集合)。
进程:可理解为执行中的程序,是线程的集合,一个操作系统中可以有多个进程,每个进程中,一定有一个线程,这个线程就是主线程。
线程:可以理解为一个执行顺序(代码自上而下运行)。
多线程:就是为了提高程序的效率(一个人盖房和一个工程队盖房)
二、应用场景
- 多线程下载,断点续传
- QQ聊天多窗口
- 爬虫(多线程同时爬取)
- 前端Ajax(异步上传)
- 分布式job(同一时刻多个任务调度)
三、如何创建线程
3.1继承Thread
public class ThreadDemo{
public static void main(String[] args) {
//线程类
ThreadTest1 t1 = new ThreadTest1 ();
//start()方法启动线程,而不是run()方法
t1.start();
}
}
class ThreadTest1 extends Thread{
/*
* run方法就是线程要执行的代码
*/
@Override
public void run() {
System.out.println("继承方式实现多线程");
}
}
3.2 实现Runable接口
public class ThreadDemo2{
public static void main(String[] args) {
//接口形式 使用接口方式比继承方式好
//使用匿名内部类的方式
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("实现Runable接口创建线程");
}
}).start();
}
}
3.2 jdk1.8 callback
后续笔记中深入讨论
3.3 使用线程池创建线程
后续笔记中深入讨论
四、守护线程与非守护线程
守护线程:和main有关,和主线程一起销毁。
用户线程:用户自己创建的线程。如果主线程停止掉,不会影响到用户线程,也叫非守护线程
。
GC线程:属于守护线程。
public class Demo {
public static void main(String[] args) {
//创建的是用户线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("子线程 i " + i);
}
}
});
//设置守护线程
t1.setDaemon(true);
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println("主线程 i " + i);
}
System.out.println("主线程执行完毕");
}
}
// 输出 因为主线程死掉后,守护线程也就死掉了,所以子线程不输出
主线程 i 0
主线程 i 1
主线程 i 2
主线程 i 3
主线程 i 4
主线程执行完毕
//如果将t1.setDaemon(true);注释掉,则输出:
主线程 i 0
主线程 i 1
主线程 i 2
主线程 i 3
主线程 i 4
主线程执行完毕
子线程 i 0
子线程 i 1
子线程 i 2
子线程 i 3
子线程 i 4
五、多线程的运行状态
1.新建状态 new Thread()
2.准备:调用start()方法,等待CPU调度,就绪状态
3.运行:CPU开始执行 run方法
4.休眠:调用sleep()方法或者wait()方法,到达时间后进入就绪状态
5.停止:run方法代码执行完毕或者调用stop方法
六、join()方法
A中调用B的join方法 ===A等待B执行完毕后,再继续执行
public class Demo {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
Thread.sleep(1000);
System.out.println("子线程 i " + i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t1.start();
//主线程,需要让子线程先执行完毕
try {
//优先级
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < 5; i++) {
System.out.println("主线程 i " + i);
}
}
}
//输出
子线程 i 0
子线程 i 1
子线程 i 2
子线程 i 3
子线程 i 4
主线程 i 0
主线程 i 1
主线程 i 2
主线程 i 3
主线程 i 4