相关概念
- 进程
- 线程—单线程/多线程
- 并发—单核CPU实现多任务
- 并行—同一时刻,多个任务同时执行。多核CPU可以实现并行
一个程序启动时,即一个进程启动以后,会默认启动一个主线程(main),可以在主线程中创建子线程Thread1,Thread2,也可以在子线程中继续创建子线程,
主线程的生命周期和子线程不一定相同,可能主线程已经结束了,子线程还在继续执行。
同一个应用程序可以有多个进程,和多个线程
创建线程
创建线程的两种方式
a. 继承Threadclass A extends Thread{@Overridepublic void run() {//do something}}}
b. 实现Runnable—由于Java中不支持多继承,如果一个类A已经继承了其他的类,如果A还想继续在里面实现多线程,则无法继承Thread来实现,这时候可以使用Runnable
class A extends B implements Runnable{@Overridepublic void run() {//do something}}}
这两种方式本质上没有区别,都是走的start0()函数,Runnable更加适合多个线程共享一个资源的情况,避免单继承的限制

售票系统
线程退出(中断线程)
- 通知方式
public class ThreadExitDemo {public static void main(String[] args) throws InterruptedException {MyThread myThread = new MyThread();myThread.start();//休眠10秒,通知线程退出Thread.sleep(5000);//通知线程退出myThread.setLoop(false);}}class MyThread extends Thread {//提供方法用于外部来通知线程内部退出public void setLoop(boolean loop) {this.loop = loop;}//设置一个控制变量private boolean loop = true;@SneakyThrows@Overridepublic void run() {while (loop) {Thread.sleep(50);System.out.println("====");}}}
- 线程常用方法
- setName
- getName
- start—底层调用run()方法,run方法本身不会创建线程,run()里面调用的start0()会开启线程,由CPU决定如何调度
- run
- setPriority
- getPriority
- interrupt—中断线程,没有正真结束线程,一般用于中断正在休眠的线程
- sleep
- yield—让出CPU供其他线程执行,不一定成功
- join—线程插队 在主线程中执行t.goin(),则表示先执行完子线程在回到主线程中继续执行
package com.example.usage;import lombok.SneakyThrows;/*** @author chenzhian* @description 线程常用方法示例* @date 2021年05月07日 15:08*/public class ThreadMethodDemo {public static void main(String[] args) throws InterruptedException {// 调用对方的join方法T t = new T();t.start();for (int i = 0; i < 10; i++) {Thread.sleep(1000);System.out.printf("[主线程] %s 正在做事 %d \n", Thread.currentThread().getName(), i);// 主线程执行到第5个时,让出CPU资源,让子线程执行完我再继续执行if (i == 5) {System.out.println("干大事的先来...");// 关键方法--这里让t执行完毕t.join();// Thread.yield();//不一定能让成功System.out.println("现在又轮到主线程继续干事情了");}}}}class T extends Thread {@SneakyThrows@Overridepublic void run() {for (int i = 0; i < 20; i++) {Thread.sleep(500);System.out.printf("[子线程] %s 干了 %d 件大事 \n", Thread.currentThread().getName(), i);}}}
守护线程
守护线程示例
package com.example.usage;import lombok.SneakyThrows;/*** @author chenzhian* @description 守护线程示例--主线程退出以后,守护线程自动结束* @date 2021年05月07日 15:58*/public class DaemonThreadDemo {public static void main(String[] args) throws InterruptedException {MyDaemonThread myDaemonThread = new MyDaemonThread();// [1] 设置为守护线程myDaemonThread.setDaemon(true);myDaemonThread.start();for (int i = 0; i < 10; ++i) {Thread.sleep(1000);System.out.printf("宝宝玩了 %d 个小时了 \n", i);}}}class MyDaemonThread extends Thread {@SneakyThrows@Overridepublic void run() {// 无限循环for (; ; ) {Thread.sleep(1000);System.out.println("爸爸妈妈在看着孩子");}}}
线程状态/生命周期


public class ThreadLifeScopeDemo {public static void main(String[] args) throws InterruptedException {T2 t = new T2();System.out.printf("[%s] --> %s \n", t.getName(), t.getState());t.start();while (Thread.State.TERMINATED != t.getState()) {System.out.printf("[%s] --> %s \n", t.getName(), t.getState());Thread.sleep(500);}// 主线程休眠10秒,通知线程退出Thread.sleep(5000);// 通知线程退出t.setLoop(false);System.out.printf("[%s] --> %s \n", t.getName(), t.getState());}}class T2 extends Thread {// 设置一个控制变量private boolean loop = true;// 提供方法用于外部来通知线程内部退出public void setLoop(boolean loop) {this.loop = loop;}@SneakyThrows@Overridepublic void run() {while (true) {for (int i = 0; i < 10; ++i) {System.out.println("test Thread State");Thread.sleep(500);}//for循环以后退出break;}}}
输出:
[Thread-0] --> NEW[Thread-0] --> RUNNABLEtest Thread Statetest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLEtest Thread State[Thread-0] --> RUNNABLE[Thread-0] --> TERMINATEDProcess finished with exit code 0
线程同步—Synchronized
当一个线程在对内存进行操作时,其他线程不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能够对该地址进行操作

互斥锁&死锁



- 线程死锁
- 释放锁

