【JavaSE】初识线程,线程与进程的区别

文章目录

✍线程是什么?

⼀个线程就是⼀个 "执行流". 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时" 执⾏着多份代码.

✍线程和进程的区别

  • 进程是包含线程的. 每个进程⾄少有⼀个线程存在,即主线程
  • 进程和进程之间不共享内存空间. 同⼀个进程的线程之间共享同⼀个内存空间.
  • 进程是系统分配资源的最⼩单位,线程是系统调度的最⼩单位。
  • ⼀个进程挂了⼀般不会影响到其他进程. 但是⼀个线程挂了, 可能把同进程内的其他线程⼀起带⾛(整个进程崩溃).

进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。

与进程不同的是同类的多个线程共享进程的堆和方法区资源 ,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈 ,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程

为什么虚拟机栈,本地方法区,程序计数器是私有的?
程序计数器

  1. 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,如:顺序执行、选择、循环、异常处理。
  2. 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。

和PCB中的上下文联系起来:

在上文中,我们提到"并发执行",在执行过程中,会产生很多的"中间结果",在进程切出于CPU之前,需要把这些"中间结果"(CPU的寄存器中的各种值),保存到PCB的上下文中。

这个过程是将寄存器的数据存放到内存中,也就是我们平时所见的【存档】

当下一次CPU再次调度这个进程时,就要把之前的数据读取出来,放入寄存器中,也就是所谓的【读档】。

具体操作过程:有一个PC程序计数器,他会记录上一次执行到哪一个位置,在下一次执行时,就从这个位置继续执行。

虚拟机栈:每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。

本地方法栈:和虚拟机栈所发挥的作用非常相似,区别是: 虚拟机栈为虚拟机执行 Java 方法 (也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。 在 HotSpot 虚拟机中和 Java 虚拟机栈合二为一。

✍线程的创建

1.继承 Thread 类

java 复制代码
class MyThread extends Thread{
    @Override
    public void run() {
        while (true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class demo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread();
        t.start();
        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

2.实现Runnable接口

java 复制代码
class MyRunnable implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("hello thread2");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class demo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new MyRunnable());
        t.start();
        while (true){
            System.out.println("hello main2");
            Thread.sleep(1000);
        }
    }
}

3.匿名内部类

java 复制代码
public class demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(){
            @Override
            public void run() {
                while (true){
                    System.out.println("hello thread3");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start();
        while (true){
            System.out.println(" hello main");
            Thread.sleep(1000);
        }
    }
}

4.匿名内部类创建 Runnable ⼦类对象

java 复制代码
public class demo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread((Runnable) () ->{
           while (true){
               System.out.println("hello thread4");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        t.start();
        while (true){
            System.out.println(" hello main4");
            Thread.sleep(1000);
        }
    }
}

5.lambda 表达式创建 Runnable ⼦类对象

java 复制代码
public class demo5 {
    public static void main(String[] args)  {
        Thread t = new Thread(()->{
          while (true){
              System.out.println("hello thred5");
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
          }
        });
        t.start();
        while (true){
            System.out.println(" hello main5");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

运行结果为两个线程交替执行。

由于没有终止条件,这两个线程会一直执行下去。

相关推荐
wuminyu6 小时前
专家视角看Java字节码加载与存储指令机制
java·linux·c语言·jvm·c++
callJJ7 小时前
Spring Data Redis 两种编程模型详解:同步 vs 响应式
java·spring boot·redis·python·spring
wbs_scy8 小时前
Linux线程同步与互斥(三):线程同步深度解析之POSIX 信号量与环形队列生产者消费者模型,从原理到源码彻底吃透
java·开发语言
jinanwuhuaguo9 小时前
(第三十三篇)五月的文明奠基:OpenClaw 2026.5.2版本的文明级解读
android·java·开发语言·人工智能·github·拓扑学·openclaw
xmjd msup10 小时前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
9523610 小时前
SpringBoot统一功能处理
java·spring boot·后端
Lyyaoo.10 小时前
优惠券秒杀业务分析
java·开发语言
消失的旧时光-194310 小时前
统一并发模型:线程、Reactor、协程本质是一件事(从线程到协程 · 第6篇·终章)
java·python·算法
勿忘初心122110 小时前
Java 国密 SM4 加密工具类实战(Hutool + BouncyCastle)|企业级数据加密 + 兼容 JDK8
java·数据安全·数据加密·后端开发·企业级开发·国密 sm4
庞轩px10 小时前
第8篇:原子类与CAS底层原理——无锁并发的实现
java·cas·乐观锁·aba·无锁编程·自旋