初识多线程(超详细)

发布时间:2024年01月18日

目录

1.什么是多线程

2.为什么要有线程(线程的优点)

?2.1线程和进程的区别

3.Java 的线程 和 操作系统线程 的关系

4.创建一个多线程程序

方法一.继承Thread 重写run

方法二 实现Runnable 接口 ,重写run

什么是runnable:

方法三:实现Runnable 重写run 匿名内部类

什么是匿名内部类

方法4:lambda 表达式创建 Runnable ?类对象


1.什么是多线程

? ? ? 多线程是指在一个程序中同时执行多个线程的并发编程技术。线程是程序的基本执行单元,一个进程可以包含多个线程。每个线程都有自己的执行路径,可以独立地执行特定的任务或代码块.多线程的主要目的是提高程序的并发性和效率。通过在一个程序中使用多个线程,可以实现同时执行多个任务,从而充分利用多核处理器和计算资源,加快程序的运行速度。

?? ? ?举例:? 有一个项目你一个人做的话费时费力,你可以和几个朋友一起组队完成项目。每个人负责不同的任务,比如设计、编程和测试。你们可以同时进行工作,每个人在自己的线程上执行特定的任务,最后将结果整合在一起。

2.为什么要有线程(线程的优点)

?先, "并发编程" 成为 "刚需".
? 单核 CPU 的发展遇到了瓶颈. 要想提?算?, 就需要多核 CPU. ?并发编程能更充分利?多核 CPU?资源.
? 有些任务场景需要 "等待 IO", 为了让等待 IO 的时间能够去做?些其他的?作, 也需要?到并发编程. 其次, 虽然多进程也能实现 并发编程, 但是线程?进程更轻量.
? 创建线程?创建进程更快.
? 销毁线程?销毁进程更快.
? 调度线程?调度进程更快

?2.1线程和进程的区别

进程定义:??进程是程序在执行过程中的一个实例,拥有独立的内存空间、代码段、数据段和堆栈等资源.

线程定义:线程是进程中的一个执行单元,每个线程都共享相同的内存空间和资源,可以访问进程中的全局变量和静态变量。

?进程调度:进程是由操作系统负责进行调度和资源分配,每个进程拥有独立的调度队列和优先级

?线程调度:线程是由进程内的调度器进行管理和调度,所有线程共享进程的调度队列和优先级。

进程并发性:进程是操作系统中的独立执行单元,它们之间相互独立,各自运行并发执行

线程并发性:是在同一进程内执行,它们共享进程的资源,可以实现更细粒度的并发控制。

注意:?

1.进程是系统分配资源的最?单位,线程是系统调度的最?单位。

2.?个进程挂了?般不会影响到其他进程. 但是?个线程挂了, 可能把同进程内的其他线程?起带?(整 个进程崩溃).
3.进程是包含线程的.多个线程共享同一份资源.

3.Java 的线程 和 操作系统线程 的关系

? ? ? ? 首先我们要知道Java 的线程是建立在操作系统线程之上的。Java 虚拟机 (JVM) 使用操作系统提供的原生线程(操作系统线程)来实现 Java 线程,即每个 Java 线程都会分配一个对应的操作系统线程进行支持。 线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对??层提供了?些 API 供用户使?(例如 Linux 的 pthread 库). Java 标准库中 Thread 类可以视为是对操作系统提供的 API (是应用程序编程接口的缩写,是一组定义程序之间如何进行通信和交互的规范。它提供了一系列的函数、类或方法,用于让开发者能够方便地访问系统或软件的某些功能或服务。) 进?了进?步的抽象和封装.封装成了java风格的api.

4.创建一个多线程程序

方法一.继承Thread 重写run

1.继承 Thread 来创建?个线程类.
//1.创建一个类继承Theard
class MyThead extends Thread{
   @Override//检测是否有错
    public void run(){
       //run方法就是该线程的入口方法
       System.out.println("hello word");
   }
}

2.创建 MyThread 类的实例?

 //根据刚才的类,创建出示例
        //MyThread t = new MyThread();都可以
        Thread t = new MyThead();

3.调? start ?法启动线程?

 //调用Thread 的start 方法, 才会真正调用系统的api, 在系统中创建出线程。
        t.start();

? 它就会打印出hello world.但是这样并不能体现出多线程,我们再写个程序.

和上面的步骤一样我们写两个死循环.

package 多线程;

class MyThread2 extends Thread{
    @Override
    public void run(){
        while (true){
            System.out.println("hello thread");
        }
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        Thread t = new MyThread2();
        t.start();


        while (true){
            System.out.println("hello main");
        }
    }
}

我们同时写两个死循环.我们知道一旦进入一个死循环另一个是无法被执行的.

我们来看结果

我们发现不仅输出了hello thread 也输出了hello main这说明两个死循环都被执行了.其实它们两个是并发执行的,所以才会两个都打印了.

由于输出的太快了很难看到,所以我们加上sleep方法.

package 多线程;

class MyThread2 extends Thread{
    @Override
    public void run(){
        while (true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class ThreadDemo2 {


    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread2();
        t.start();


        while (true){
            System.out.println("hello main");
           Thread.sleep(1000);
        }
    }
}

? ? ? 注意:当有多个线程的时候,这些线程执行的先后顺序是不确定的.因为操作系统内核中有一个'调度器'模块,这个模块的实现方法类似于"随机调度'的效果.

? ? ? 随机调度:是指操作系统在执行进程时,随机选择一个就绪进程进行调度,而不是按照某种固定的规则或优先级进行调度。

方法二 实现Runnable 接口 ,重写run

什么是runnable:

Runnable 是一个接口,用于表示可以被线程执行的任务。它只有一个方法 run(),用于定义线程的执行逻辑。

package 多线程;

class MyThread3 implements Runnable{
    @Override
    public void run(){
        while (true){
            System.out.println("hello runnable");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
public class ThreadDemo3 {
    public static void main(String[] args)  {
        Thread t= new Thread(new MyThread3());
       t.start();
        
        while (true) {
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

我们看运行的结果

和上一种运行方法结果一样.

方法三:实现Runnable 重写run 匿名内部类

什么是匿名内部类

? ? ? ? 匿名内部类是一种没有名字的内部类,通常用于临时定义一个类,并创建其对象。它可以用于实现接口或继承类,并重写其中的方法。匿名内部类的语法比较特殊,可以在定义一个对象的同时创建一个新的类。匿名内部类只能用一次,不能重复使用.

package 多线程;

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {//Thread构造方法的参数,填写了runnable的匿名内部类的实例
            @Override
            public void run() {
                while (true){
                    System.out.println("hello runnable");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        t.start();

        while (true){
            System.out.println("hello main");

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

方法4:lambda 表达式创建 Runnable ?类对象

// 使? lambda 表达式创建 Runnable ?类对象
Thread t3 = new Thread(() -> System.out.println("使?匿名类创建 Thread ?类对象"));
Thread t4 = new Thread(() -> {
 System.out.println("使?匿名类创建 Thread ?类对象");
});

希望大家多多支持!

文章来源:https://blog.csdn.net/weixin_71841320/article/details/135670164
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。