ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Java 多线程基础

2026/9/25 0:14:40 拓冰建站 浏览量
Java 多线程基础

一、线程相关概念

1.程序

2.进程

3.线程



 二、线程的基本使用

1.创建线程的两种方式

1.1 继承 Thread 类

public class Thread01 {public static void main(String[] args) throws InterruptedException {//创建 Cat 对象,可以当做线程使用Cat cat = new Cat();cat.start();//启动线程-> 最终会执行 cat 的 run 方法//cat.run();//run 方法就是一个普通的方法, 没有真正的启动一个线程,就会把 run 方法执行完毕,才向下执行/*(1)public synchronized void start() {start0();}(2)//start0() 是本地方法,是 JVM 调用, 底层是 c/c++实现//真正实现多线程的效果, 是 start0(), 而不是 runprivate native void start0();*///说明: 当 main 线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行//这时 主线程和子线程是交替执行..System.out.println("主线程继续执行" + Thread.currentThread().getName());//名字 mainfor(int i = 0; i < 60; i++) {System.out.println("主线程 i=" + i);Thread.sleep(1000); //让主线程休眠}}
}class Cat extends Thread {//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用//2. 我们会重写 run 方法,写上自己的业务代码//3. run Thread 类 实现了 Runnable 接口的 run 方法/*@Overridepublic void run() {if (target != null) {target.run();}}*/int times = 0;@Overridepublic void run() {//重写 run 方法,写上自己的业务逻辑while (true) {//在控制台输出 “喵喵, 我是小猫咪”System.out.println("喵喵, 我是小猫咪" + (++times) + " 线程名=" + Thread.currentThread().getName());//让该线程休眠 1 秒 ctrl+alt+ttry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//当 times 到 80, 退出 while, 这时线程也就退出..if(times == 80) {break;}}}
}

1.2 实现 Runnable 接口

public class Thread02 {public static void main(String[] args) {Dog dog = new Dog();//dog.start(); 这里不能调用 start//创建了 Thread 对象,把 dog 对象(实现 Runnable),放入 ThreadThread thread = new Thread(dog);thread.start();// Tiger tiger = new Tiger();//实现了 Runnable// ThreadProxy threadProxy = new ThreadProxy(tiger);// threadProxy.start();}
}class Animal {
}class Tiger extends Animal implements Runnable {@Overridepublic void run() {System.out.println("老虎嗷嗷叫....");}
}//线程代理类 , 模拟了一个极简的 Thread 类
class ThreadProxy implements Runnable {//你可以把 Proxy 类当做 ThreadProxyprivate Runnable target = null;//属性,类型是 Runnable@Overridepublic void run() {if (target != null) {target.run();//动态绑定(运行类型 Tiger)}}public ThreadProxy(Runnable target) {this.target = target;}public void start() {start0();//这个方法时真正实现多线程方法}public void start0() {run();}
}class Dog implements Runnable { //通过实现 Runnable 接口,开发线程int count = 0;@Overridepublic void run() { //普通方法while (true) {System.out.println("小狗汪汪叫..hi" + (++count) + Thread.currentThread().getName());//休眠 1 秒try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (count == 10) {break;}}}
}

1.3 多线程执行

 

public class Thread03 {public static void main(String[] args) {T1 t1 = new T1();T2 t2 = new T2();Thread thread1 = new Thread(t1);Thread thread2 = new Thread(t2);thread1.start();//启动第 1 个线程thread2.start();//启动第 2 个线程}
}class T1 implements Runnable {int count = 0;@Overridepublic void run() {while (true) {//每隔 1 秒输出 “hello,world”,输出 10 次System.out.println("hello,world " + (++count));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(count == 60) {break;}}}
}class T2 implements Runnable {int count = 0;@Overridepublic void run() {//每隔 1 秒输出 “hi”,输出 5 次while (true) {System.out.println("hi " + (++count));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(count == 50) {break;}}}
}

1.4 继承 Thread vs 实现 Runnable 的区别


2.线程终止


3.线程的常用方法



三、用户线程和守护线程

 如何将一个线程设置成守护线程

public class ThreadMethod03 {public static void main(String[] args) throws InterruptedException {MyDaemonThread myDaemonThread = new MyDaemonThread();//如果我们希望当main线程结束后,子线程自动结束//,只需将子线程设为守护线程即可myDaemonThread.setDaemon(true);myDaemonThread.start();for( int i = 1; i <= 10; i++) {//main线程System.out.println("宝强在辛苦的工作...");Thread.sleep(1000);}}
}class MyDaemonThread extends Thread {public void run() {for (; ; ) {//无限循环try {Thread.sleep(1000);//休眠1000毫秒} catch (InterruptedException e) {e.printStackTrace();}System.out.println("马蓉和宋喆快乐聊天,哈哈哈~~~");}}
}


四、线程的生命周期

1.线程的状态

2.线程状态转换图

 3.查看线程状态

public class ThreadState_ {public static void main(String[] args) throws InterruptedException {T t = new T();System.out.println(t.getName() + " 状态 " + t.getState());t.start();while (Thread.State.TERMINATED != t.getState()) {System.out.println(t.getName() + " 状态 " + t.getState());Thread.sleep(500);}System.out.println(t.getName() + " 状态 " + t.getState());}
}class T extends Thread {@Overridepublic void run() {while (true) {for (int i = 0; i < 10; i++) {System.out.println("hi " + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}break;}}
}


 五、线程同步

1.线程同步机制

2.线程同步方法

 使用多线程,模拟三个窗口同时售票 100 张(不加锁之前)--出现超卖现象

public class SellTicket {public static void main(String[] args) {// 方法一:继承 Thread 类// SellTicket01 sellTicket01 = new SellTicket01();// SellTicket01 sellTicket02 = new SellTicket01();// SellTicket01 sellTicket03 = new SellTicket01();// sellTicket01.start();//启动售票线程// sellTicket02.start();//启动售票线程// sellTicket03.start();//启动售票线程// 方法二:使用实现 Runable 接口方式来售票SellTicket02 sellTicket02 = new SellTicket02();new Thread(sellTicket02).start();//第 1 个线程-窗口new Thread(sellTicket02).start();//第 2 个线程-窗口new Thread(sellTicket02).start();//第 3 个线程-窗口}
}//使用 Thread 方式
class SellTicket01 extends Thread {private static int ticketNum = 100;//让多个线程共享 ticketNum@Overridepublic void run() {while (true) {if (ticketNum <= 0) {System.out.println("售票结束...");break;}//休眠 50 毫秒, 模拟try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));}}
}//实现接口方式
class SellTicket02 implements Runnable {private int ticketNum = 100;//让多个线程共享 ticketNum@Overridepublic void run() {while (true) {if (ticketNum <= 0) {System.out.println("售票结束...");break;}//休眠 50 毫秒, 模拟try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));//1 - 0 - -1 - -2}}
}

使用多线程,模拟三个窗口同时售票 100 张(加锁之后)--不会出现超卖现象

public class SellTicket {public static void main(String[] args) {SellTicket03 sellTicket03 = new SellTicket03();new Thread(sellTicket03).start();//第 1 个线程-窗口new Thread(sellTicket03).start();//第 2 个线程-窗口new Thread(sellTicket03).start();//第 3 个线程-窗口}
}//实现接口方式, 使用 synchronized 实现线程同步
class SellTicket03 implements Runnable {private int ticketNum = 100;//让多个线程共享 ticketNumprivate boolean loop = true;//控制 run 方法变量Object object = new Object();//同步方法(静态的):锁为当前类本身,加在 SellTicket03.class//1.同步静态方法public synchronized static void m1() {}//2.在静态方法中实现同步代码块public static void m2() {synchronized (SellTicket03.class) {System.out.println("m2");}}//同步方法(非静态的):锁在 this 对象//1.同步方法,在同一时刻, 只能有一个线程来执行 sell 方法public synchronized void sell() { //2.同步代码块, 互斥锁还是在 this 对象synchronized (/*this*/ object) {if (ticketNum <= 0) {System.out.println("售票结束...");loop = false;return;}//休眠 50 毫秒, 模拟try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));//1 - 0 - -1 - -2}}@Overridepublic void run() {while (loop) {sell();//sell 方法是一共同步方法}}
}

3.互斥锁

4.死锁

5.释放锁



 六、参考

B站 韩顺平零基础学Java