多线程 (进阶+初阶)

本文详细介绍了线程的基础知识,包括进程与线程的区别、Java中创建线程的多种方式、线程的中断、常用线程方法及特性,以及线程安全、synchronized关键字、volatile的内存可见性、线程间通信和单例模式的应用。通过实例和面试重点,深入剖析了线程的各个方面,帮助读者理解和掌握Java多线程编程。
摘要由CSDN通过智能技术生成

文章目录

一、进程和线程是什么

1.1程序

在这里插入图片描述
在这里插入图片描述

1.2端口号和PID

在这里插入图片描述

1.3进程和线程

在这里插入图片描述
在这里插入图片描述

有进程实现并发编程为什么还要使用线程?

虽然多进程也能实现并发编程, 但是线程比进程更轻量:所以线程又叫轻量级进程;
创建线程比创建进程更快;
销毁线程比销毁进程更快;
调度线程比调度进程更快;

两者区别(面试重点)

在这里插入图片描述
在这里插入图片描述
Tset就是进程,main是主线程,此时多余的一个进程java.exe是idea自己
在这里插入图片描述
总结:
在这里插入图片描述

1.4串行、并行、并发

在这里插入图片描述

二、Java.lang.Thread

2.1第一个多线程代码

注意事项:
1.启动线程是start方法,不是run方法。通过start方法将线程启动以后,每个线程自动执行自己的run方法
2.Thread-0这些线程名字是默认的,可以修改
3.这四个线程同时执行,互不影响
在这里插入图片描述
在这里插入图片描述

2.2 jconsole命令

在这里插入图片描述

2.3创建线程的四种方法(重点)

在这里插入图片描述
在这里插入图片描述

继承Thread类

继承Thread的子类就是一个线程实体

// 定义一个Thread类,相当于一个线程的模板
class MyThread01 extends Thread {
   
    // 重写run方法
    // run方法描述的是线程要执行的具体任务
    @Overridepublic
     void run() {
   
        System.out.println("hello, thread.");
    }
}
 
/**
 * 继承Thread类并重写run方法创建一个线程
 * @author  rose
 * @created 2022-06-20
 */
public class Thread_demo01 {
   
    public static void main(String[] args) {
   
        // 实例化一个线程对象
        MyThread01 t = new MyThread01();
        // 真正的去申请系统线程,参与CPU调度
        t.start();
    }
}

在这里插入图片描述

实现Runnable接口

这个实现Runnable接口的子类,并不是真正的的线程实体,只是线程的一个核心工作任务。这是和第一种方法最大的区别

// 创建一个Runnable的实现类,并实现run方法
// Runnable主要描述的是线程的任务
class MyRunnable01 implements Runnable {
   
    @Overridepublic void run() {
   
        System.out.println("hello, thread.");
    }
}
/**
 * 通过实现Runnable接口并实现run方法
 * @author rose
 * @created 2022-06-20
 */
public class Thread_demo02 {
   
    public static void main(String[] args) {
   
        // 实例化Runnable对象
        MyRunnable01 runnable01 = new MyRunnable01();
        // 实例化线程对象并绑定任务
        Thread t = new Thread(runnable01);
        // 真正的去申请系统线程参与CPU调度
        t.start();
    }
}

1.创建线程任务对象
2.创建线程对象,并传入任务对象
3.调用Thread类的start方法启动线程
在这里插入图片描述

两种方式各自优势

1.两种方式创建线程最后都是通过Thread类的start方法启动线程
2.继承Thread类方法创建线程属于单继承,有局限性
3.实现Runnable接口的子类更加灵活,不仅实现Runnable接口,还可以继承其他类
4.调用当前线程的区别:继承Thread类,直接使用this就表示当前线程对象的引用;实现Runnable 接口, this 表示的是 MyRunnable 的引用. 需要使用 Thread.currentThread()
在这里插入图片描述

两种创健线程方式的不同写法

匿名内部类继承Thread类和实现Runnable接口

在这里插入图片描述
在这里插入图片描述

/**
 * @author hide_on_bush
 * @date 2022/7/12
 */
public class OtherMethod {
   
    public static void main(String[] args) {
   
        //1.匿名内部类继承Thread类
        Thread thread=new Thread(){
   
            @Override
            public void run() {
   
                System.out.println("这是匿名内部类继承Thread类");
                System.out.println(Thread.currentThread().getName());
            }
        };
        //2.匿名内部类实现Runnable接口
        Thread runThread=new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                System.out.println("这是匿名内部类实现Runnable接口");
                System.out.println(Thread.currentThread().getName());
            }
        });
        thread.start();
        runThread.start();
        System.out.println("这是主线程"+Thread.currentThread().getName());
    }
}

在这里插入图片描述

Lambda表达式

lambda表达式是建立在函数式接口,只有一个抽象方法!!!
在这里插入图片描述

//3.Lambad
        Thread lambadaThread=new Thread(()-> System.out.println("这是Lambda表达式实现Runnable接口"));

实现Callable接口

在这里插入图片描述

  • 使用线程池实现Callable接口,FutureTast是Future子类
    在这里插入图片描述

2.4并发和串行时间对比

理论上:并发执行速度是顺序执行的一倍,所以串行耗时应该是并发的一倍

实际上:线程的创建、销毁和调用也会耗时,所以实际的时间比理论实践多一点

结论:多线程的最大好处就是调高系统处理效率
在这里插入图片描述

2.5 练习

在这里插入图片描述
正解:可能先打印1也可能先打印2,具体先调度子线程输出还是先调度主线程输出由系统决定。
至于为什么多次试验都是 21的结果:子线程位于主线程中,当t.start时主线程已经在运行,所以往往都先跑主线程才看到子线程结果
在这里插入图片描述
在这里插入图片描述

public class Thread_2533 {
   
    public static void main(String[] args) throws InterruptedEx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值