• 多线程编程(1)


    本篇重点

    1. 了解进程和线程的区别和联系
    2. 使用Java,实现创建线程的五种写法


    上一篇博客中重点介绍了进程的调度,本篇让我们一起来学习线程吧!

    为什么更加青睐于使用多线程去解决并发的问题?

    因为
    进程,是比较“重量级”的,它不仅仅速度比较慢而且消耗资源多
    创建一个进程,成本比较高
    销毁一个进程,成本也比较高
    调度一个进程,成本也挺高
    所以,多进程编程,可以解决并发的问题,但是并不是一个高效的选择!!!
    线程,则是更加轻量的进程(轻量级进程)

    线程为什么比进程更加轻量?

    1. 线程与进程共用同一份进程的系统资源(1. 内存空间 2. 文件描述符表)(意味着,对于线程而言,系统资源是已经分配好了的,创建线程就省下了分配资源的开销)

    线程
    进程包含线程
    一个进程里可以有一个线程,或者多个线程
    每个线程都是独立的执行流.多个线程之间,也是并发执行的
    操作系统,真正调度的,是在调度线程,而不是进程

    线程是操作系统调度运行的基本单位 \color{red}{线程是操作系统调度运行的基本单位} 线程是操作系统调度运行的基本单位

    多进程与多线程的吃鸡方式
    多进程吃鸡方式
    在这里插入图片描述
    多线程吃鸡方式
    在这里插入图片描述
    优化吃鸡过程
    在这里插入图片描述
    再优化吃鸡过程的思考
    在这里插入图片描述
    如果一个线程出现了问题,那么会发生什么呢??
    在这里插入图片描述

    进程与线程的区别

    进程和线程的区别: \color{red}{进程和线程的区别:} 进程和线程的区别:

      1. 进程包含线程
      2. 进程有自己独立的内存空间和文件描述符表.同一个进程中的多个线程之间,共享同一份地址空间和文件描述符表
      3. 进程是操作系统资源分配的基本单位,线程是操作系统调度执行的基本单位
      4. 进程之间具有独立性,一个进程挂了,不会影响到别的进程;同一个进程里的多线程之间,一个线程挂了,可能会把整个进程带走,影响到其他线程
    
    • 1
    • 2
    • 3
    • 4

    使用Java进行多线程编程

    方法一:继承 Thread, 重写 run

    class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println("hello t");
        }
    }
    public class ThreadDemo1 {
        public static void main(String[] args) {
            Thread t = new MyThread();
            t.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    想要结果更加明显一点可以加个for循环进行标记

    class MyThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println("hello t  -- "+i);
            }
        }
    }
    public class ThreadDemo1 {
        public static void main(String[] args) {
            Thread t = new MyThread();
            t.start();
            for (int i = 0; i < 30; i++) {
                System.out.println("hello main  -- "+i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    可以看出这里是随机进行打印的

    使用sleep函数方便进行结果的查看

    class MyThread extends Thread{
        @Override
        public void run() {
            while (true) {
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public class ThreadDemo1 {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new MyThread();
            t.start();
            while (true) {
                System.out.println("hello main");
                Thread.sleep(1000);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    上述代码涉及到两个线程

    1. main 方法所对应的线程(一个进程至少得有一个线程)也可以称为主线程
    2. 通过t.start创建的新线程

    如何使用工具对进程进行查看呢??

    找到你的jdk --> bin --> jconsole.exe
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    方法二: 实现 Runnable, 重写 run

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            while (true) {
                System.out.println("hello t");
                
            }
        }
    }
    public class ThreadDemo2 {
        public static void main(String[] args) {
            MyRunnable runnable = new MyRunnable();
            Thread t = new Thread(runnable);
            t.start();
            while (true) {
                System.out.println("hello main");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    方法三: 继承 Thread, 重写 run, 使用匿名内部类

    public class ThreadDemo3 {
        public static void main(String[] args) {
            Thread t = new Thread(){
                @Override
                public void run() {
                    while (true) {
                        System.out.println("hello t");
                    }
                }
            };
            t.start();
            while (true) {
                System.out.println("hello main");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    方法四: 实现 Runnable, 重写 run, 使用匿名内部类

    public class ThreadDemo4 {
        public static void main(String[] args) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true) {
                        System.out.println("hello t");
                    }
                }
            });
            t.start();
            while(true) {
                System.out.println("hello main");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    方法五: 使用 lambda 表达式

    创建线程最推荐的写法, 使用lambda表达式!! 最简单直观的写法

    public class ThreadDemo5 {
        public static void main(String[] args) {
            Thread t = new Thread(() -> {
                while(true) {
                    System.out.println("hello t");
                }
            },"我的线程");
            t.start();
            while (true) {
                System.out.println("hello main");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    以上就是多线程的五种写法啦

    进程与线程的区别总结

    线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元;而把传统的进程称为重型进程(Heavy—Weight Process),它相当于只有一个线程的任务。在引入了线程的操作系统中,通常一个进程都有若干个线程,至少包含一个线程。

    根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位

    资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

    包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

    内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的

    影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

    执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

  • 相关阅读:
    FFMPEG+SDL简单视频播放器——人脸检测
    linux环境下查看程序为什么被kill
    Java序列化流的奇妙之旅
    (vue)适合后台管理系统开发的前端框架
    11种增加访问者在网站上平均停留时间的技巧
    [当人工智能遇上安全] 10.威胁情报实体识别 (1)基于BiLSTM-CRF的实体识别万字详解
    Haskell网络编程:从数据采集到图片分析
    11、将数组中的 0 移动到末尾
    实施过程中的几个方面
    新的 Work Node 如何加入 K8s 集群 - Kubeadm ?
  • 原文地址:https://blog.csdn.net/m0_74007393/article/details/130896354