Java多线程(一)

发布于:2025-09-11 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

一. 什么是线程

二. 线程与进程的区别

三. 多线程

3.1 创建线程

3.1.1 方法1:继承Thread类

3.1.2 方法2:实现Runnable接口

3.1.3 方法3:匿名内部类创建Thread子类对象

3.1.4 方法4:匿名内部类创建Runnable子类对象

3.1.5 方法5:lambda创建Runnable子类对象【推荐】

3.2 观察线程

3.2.1使用jconsole命令观察线程

3.2.2 使用Java的调试器


一. 什么是线程

  • 线程(Thread)是操作系统进行任务调度和执行的基本单位,它隶属于进程,是进程内部可独立运行的“子任务单元”。
  • 线程也叫轻量级进程。(相较于进程,创建线程不需要申请更多的资源
  • 进程包含了线程。
  • 一个线程就是一个“执行流”,多个线程之间可以同时执行“多份“代码。

二. 线程与进程的区别

  • 进程是包含线程的,一个进程至少包含一个线程(称为主线程).
  • 进程与进程之间不共享资源(内存空间),而在同一个进程中的线程之间共享资源(内存空间).
  • 进程是操作系统分配资源的基本条件.
  • 线程是操作系统调度执行的基本条件.
  • 进程与进程之间不会相互影响,而同一个进程中的线程可能会相互影响(多线程编程中,多个线程可能会操作同一数据,这样会产生冲突,导致程序出现bug----线程安全问题

注意:

  • 增加线程的数量确实会提高代码的效率,但是当线程的数量提升超过一个度,效率不一定会提升,反而可能会降低(CPU的核心数是有限的,调度开销也会影响执行效率
  • Java生态中不鼓励使用多进程编程,非常鼓励多线程

三. 多线程

  • 线程是操作系统中的概念,对于多线程的相关操作,操作系统提供了对应的API类/方法
  • 每个线程都是一个独立的"执行流"
  • 多个线程是"并发"执行的

3.1 创建线程

3.1.1 方法1:继承Thread类

  1. 继承Thread类
  2. 创建MyThread类的实例
  3. 重写父类(Thread类)的  run()方法
  4. 调用start方法启用线程
public class MyThread extends Thread{

    @Override
    public void run() {

        while (true){
            System.out.println("MyThread");

           try {
                  Thread.sleep(1000);
               } catch (InterruptedException e) {
                throw new RuntimeException(e);
               }
        }
    }
}

public class Dom {
    public static void main(String[] args) {
        MyThread r=new MyThread();//Thread r=new MyThread();
        r.start();
        while (true)
        {
            System.out.println("hi");
           
        }
    }
}

运行代码如下:

注意:

  • 我们要执行 r 中的 run 方法时,不是直接调用的 r 的 run()方法,而是调用的 r.start() (调用Thread类的start()方法,该方法执行时会调用操作系统API在系统内部建立一个线程,当线程建立好后,就会自动执行上面重写的run方法)
  • main方法自身也对应一个线程(操作系统自动创建),也称为主线程(注意:多线程编译中不存在父/子线程的说法
  • 为防止运行循环时过快,CPU达到极限,我们可以写一个Thread.sleep()方法(Thread类的一个静态方法),让线程陷入阻塞状态,降低CPU的消耗
  • 多线程的调度是由操作系统负责的,操作系统对线程的调度可以认为时“随机”的

问:r.run( ) 与 r.start( ) 的区别:

使用 r.run( ) 时就不存在多线程,即一个执行流,就会导致先执行r.run( ),再执行后面的代码—单线程

3.1.2 方法2:实现Runnable接口

  1. 实现Runnable接口
  2. 重写run方法
  3. 创建MyRunnable实例对象
  4. 创建Thread类实例对象,调用Thread类的构造方法,将MyRunnable实例对象作为参数
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("MyRunnable");
    }
}


public class text {

    public static void main(String[] args) {
        MyRunnable r=new MyRunnable();
        Thread t=new Thread(r);
        t.start();
        System.out.println("hi");
    }
}

注意:

  • Runnable接口本身不能直接创建线程,需要借助Thread类来实现
  • Runnable自身一般不会单独执行,要搭配“载体”
  • 将MyRunnable实例对象作为参数后,调用start方法时实际是执行的MyRunnable中重写的run方法

3.1.3 方法3:匿名内部类创建Thread子类对象

  1. 创建Thread类的子类(没有名字-匿名)
  2. 重写 run()方法 
  3. 创建Thread的子类的实例,并且使用t引用指向
public class text {

    public static void main(String[] args) {
        Thread r=new Thread(){
            @Override
            public void run() {
                System.out.println("创建新线程");
            }
        };
        r.start();
    }
}

记住:调用start()才是真正的创建线程

3.1.4 方法4:匿名内部类创建Runnable子类对象

 Thread t=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("创建新线程");
            }
        });

        t.start();
    }

3.1.5 方法5:lambda创建Runnable子类对象【推荐】

 Thread m=new Thread(()->{
            System.out.println("创建新线程");

        });
        m.start();
-  () -> {... }  是 Lambda 表达式, ()  表示  run  方法没有参数, {... }  内是  run  方法的具体实现逻辑,这里通过循环打印信息模拟线程任务。
- 创建  Thread  对象时,将 Lambda 表达式传入, Thread  会在启动后执行该 Lambda 表达式所代表的  run  方法逻辑。
- 调用  thread.start()  启动线程,线程进入就绪状态,等待 CPU 调度执行,同时主线程继续执行自己的逻辑,实现多线程并发。

3.2 观察线程

3.2.1使用jconsole命令观察线程

3.2.2 使用Java的调试器


网站公告

今日签到

点亮在社区的每一天
去签到