1.什么是多线程?
Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。
这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
2.线程的基本使用
java中创建线程有两种方式:
通过继承Thread类,重写run方法,创建线程
实现Runnable接口,重写run方法,创建线程
通过继承Thread类创建线程代码示例:(此程序的任务是开启一个猫猫线程,该线程循环8此打印输出我是修猫🐱,随后结束)
/** * 多线程的基本使用 * 通过继承Thread类创建线程 */ public class ThreadUse { public static void main(String[] args) { Cat cat = new Cat(); cat.start(); // 启动线程 } } /** * 继承Thread * 该类就可以当作线程使用 */ class Cat extends Thread { // 重写run方法,写自己的业务 // run方法实现了Runnable接口的run方法 @Override public void run() { int times = 0; while (true) { System.out.println("我是修猫🐱" + (++times)); // 让线程休眠1秒 try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } if (times == 8) { break; } } } }
3.多线程控制机制
当我们开启一个线程类时,程序的调度机制时这样的:
此时如果CPU是多核就是并行执行,单核就是并发执行🎈
当程序启动一个子线程 Thread-0 ,主线程不会阻塞,会继续执行,主线程结束,Thread-0线程还未结束时,不会影响Thread-0执行,例如:
/** * 多线程的基本使用 * 通过继承Thread类创建线程 */ public class ThreadUse { public static void main(String[] args) throws InterruptedException { Cat cat = new Cat(); cat.start(); // 启动线程 // 当程序自动一个子线程 Thread-0 ,主线程不会阻塞,会继续执行 System.out.println("我还可以被输出!"); Thread.sleep(2000); System.out.println("我是修狗🐕"); } } /** * 继承Thread * 该类就可以当作线程使用 */ class Cat extends Thread { // 重写run方法,写自己的业务 // run方法实现了Runnable接口的run方法 @Override public void run() { int times = 0; while (true) { System.out.println("我是修猫🐱" + (++times)); if (times == 1){ System.out.println(Thread.currentThread().getName()); } // 让线程休眠1秒 try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } if (times == 8) { break; } } } } ---------------------------------- 输出: 我还可以被输出! 我是修猫🐱1 Thread-0 我是修猫🐱2 我是修狗🐕 我是修猫🐱3 我是修猫🐱4 我是修猫🐱5 我是修猫🐱6 我是修猫🐱7 我是修猫🐱8
4.start源码分析
当我们触发一个线程的时候,需要使用start而非直接在主线程调用方法
现在我们来看一下start底层的真面目
public synchronized void start() { if (this.threadStatus != 0) { throw new IllegalThreadStateException(); } else { this.group.add(this); boolean started = false; try { this.start0(); started = true; } finally { try { if (!started) { this.group.threadStartFailed(this); } } catch (Throwable var8) { } } } }
在start
源码里面,真正触发多线程的是此句话:
this.start0();
它是一个本地方法,由JVM机进行调用,底层是C/C++实现
真正实现多线程的效果,其实是strat0方法,而不是run方法😶🌫️
5.实现Runnable接口创建线程
java是单继承的,某些情况一个类可能已经继承了某一个父类,那么再通过继承Thread类来实现多线程,显然是不可行的
此时我们可以使用实现Runnable接口来创建线程✨
/** * 通过继承Runnable接口实现多线程 */ public class ThreadUseByRunnable { public static void main(String[] args) throws InterruptedException { Dog dog = new Dog(); // 通过创建Thread类传入dog从而执行线程 Thread thread = new Thread(dog); thread.start(); for (int i = 0; i < 5; i++) { System.out.println("主线程" + i); Thread.sleep(1000); } } } /** * 通过实现Runnable接口实现多线程 */ class Dog implements Runnable { int count = 0; @Override public void run() { while (true) { System.out.println("小狗旺旺🐕" + (++count)); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } if (count == 8) { break; } } } }
6.多个子线程实例
/** * 多个子线程案例 */ public class ChildThreads { public static void main(String[] args) { T1 t1 = new T1(); T2 t2 = new T2(); Thread thread = new Thread(t1); Thread thread1 = new Thread(t2); thread.start(); thread1.start(); } } class T1 implements Runnable { int times = 0; @Override public void run() { // 每隔1秒输出一次hello world while (true) { System.out.println("hello world" + (++times)); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } if (times == 8) { break; } } } } class T2 implements Runnable { int times = 0; @Override public void run() { while (true) { System.out.println("hi" + (++times)); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } if (times == 8) { break; } } } } ------------------------------- 两个线程交替输出: hello world1 hi1 hello world2 hi2 hello world3 hi3 hello world4 hi4 hello world5 hi5 hello world6 hi6 hello world7 hi7 hello world8 hi8
存在多个子线程时,系统的调度结构如下:
Thread
VS Runnable
🐭(建议使用Runnable
)
- 创建线程本质上没有区别,都是通过
strat0
方法
Runnable
接口更加适合多个线程共享一个资源的情况,并且避免的单继承的限制