web ——系统3

本文介绍了Java线程的基础知识,包括线程的创建、启动及进程间通信的方式等内容。重点讲解了Java中线程的实现机制及其与操作系统线程的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

进程间通信的常见方式:

内存管理中主要研究的问题:

只针对OS级别的线程:OS针对同一个进程下的线程实现“连坐”机制,一旦一个线程异常退出,OS会关闭该线程所在的整个进程

1.Java线程在代码中是如何体现的?

2.如何在代码中创建线程(最基本的方式)

3.启动线程

怎么理解t.start()做了什么?

什么情况下会出现线程调度(开始一个新的线程分配CPU)?


执行流:拥有独立pc的一套指令,不同的执行流从现象上看起来是完全独立的

1.线性地址(虚拟地址):物理地址

物理地址:真实内存中的地址

线性地址:物理地址被OS进行转换后的一个地址

引入线性地址这个概念之后,程序员不需要再考虑这个复杂性了。

MMU来管理复杂性

2.进程间通信(IPC)

理论上,进程之间是独立的,但实际上,往往是多个进程之间相互配合,来完成复杂的工作。

例如:通过workbench和mySql服务器进程进行通信,来实现的数据的增删查改

所以,有了进程之间交换数据的必要性了。

当下问题:OS进行资源分配是以进程为基本单位进行分配的,包括内存。分配给A进程的内存不会分配给B进程。所以,进程A表之间直接通过内存来进行数据交换的可能完全不存在了

所以OS需要提供一套机制,用于让A、B之间进行必要的数据交换——进程间通信


进程间通信的常见方式:

1.使用管道(pipe)    Linux时接触

2.消息队列(message queue)

3.信号量(semaphore)

4.信号(singal)    Linux时接触

5.共享内存(shared memory)

6.网络(nextwork)——mysql和workbench通信的方式

内存管理中主要研究的问题:

1.管理哪些内存已经被分配,那些内存暂时未被分配

2.已经分配出去的内存,何时进行回收、如何进行回收

3.物理地址 <->线性地址相互转换

4.内存碎片


1.现在介绍的都是OS系统层面地线程

thread(线)

2.进程(process)和线程(thread)的关系

进程和线程是1:m的关系,一个线程一定属于一个进程,一个进程下可以允许有多个线程

一个进程内至少有一个线程,通常被这个一开始就存在的线程,成为主线程(Main thread)

主线程和其他线程之间地位是完全相等的,没有任何特殊性

3.为啥引入线程thread的概念?

由于进程这一概念天生就是资源隔离的,所以进程挚爱金进行数据通信注定是一个高成本的工作

现实中,一个任务需要多个执行流一起配合完成,是非常罕见地

所以,需要一种方便数据通信的执行流概念出来,线程就承担了这一职责。

4.什么是线程?

线程是OS进行调度的基本单位

线程变成了独立执行流的承载概念,进程退化成只是资源(不含CPU的承载单位)

比如:

运行一个程序,没有线程之前,OS创建进程,分配资源,给定一个唯一的PC,进行运行

有了线程之后,OS创建线程,分配资源。创建线程(主线程),给定一个唯一的PC,进行运行


高级语言中的语句经过编译之后会变成一条或者多条指令

执行流:拥有独立PC的一个或者一组指令

进程:OS进行资源分配的基本单位(不包含CPU资源)

线程:OS进行调度的单位(包含CPU资源)

程序的一次执行过程表现为一个进程,main所在的线程就是主线程,主线程可以手动的创建其他线程,我们来试着跑一下两个线程:

public class AboutThread {
    static class SomeThread extends Thread{
        @Override
        public void run() {
            int i =0;
          while(true){
              System.out.println("我是另一个线程(执行流B)" + (i++));//语句1
              try {
                 TimeUnit.MILLISECONDS.sleep(139);  //ms  语句2
                  //millisecond是千分之一秒,毫秒
              } catch (InterruptedException e) {
                 // e.printStackTrace();
              }
          }
        }
    }
    
    public static void main(String[] args) {
        //在主线程中,利用SomeClass对象,创建出一个新的线程出来
        SomeThread st = new SomeThread();
        st.start();

        int i =0;
        while(true){
            System.out.println("我是主线程(执行流A)" +(i++));//语句1
            try{
                TimeUnit.MILLISECONDS.sleep(257);//语句2
            } catch (InterruptedException e) {
            }
        }
    }
}

运行结果如图:


只针对OS级别的线程:OS针对同一个进程下的线程实现“连坐”机制,一旦一个线程异常退出,OS会关闭该线程所在的整个进程

接下来的所有学习针对的都是JVM中规定的线程

不同JVM有不同的实现,他们的外在表现基本一致,除了极个别的现象

我们使用的HotSpot实现(JVM),使用一个OS原生线程来实现一个Java线程

(Java线程,一个想爱你成异常关闭,不会连坐)

Java中的进程由于有JVM的存在,所以使得Java中做多进程级别的开发基本很少。Java中的线程还克服了操作系统线程的很多缺点。所以,在Java开发中,我们使用多线程模型来进行来发,很少使用多进程模型。


1.Java线程在代码中是如何体现的?

java.lang.Thread类(包括其子类的)一个对象

2.如何在代码中创建线程(最基本的方式)

Thread   线程

Runnable 让这个线程去完成的工作(任务)

      a.通过重写Thread类,并且重写run方法

           实例化该类的对象 ->Thread对象

public class MyFirstThreadClass extends Thread{

    public MyFirstThreadClass(){
        System.out.println("可以正常使用构造方法之类的");
    }
    
    @Override
    public void run() {
        //这个方法下写的所有代码,如果正确创建线程的话,都会运行在新的线程执行流中
        System.out.println("我的第一个线程");
    }
}
public class Main {
    public static void main(String[] args) {
        MyFirstThreadClass t = new MyFirstThreadClass();
        //t指向了一个创建出来的线程对象
        //线程创建好了,但并没有运行起来
    }
}

      b.通过实现Runnable接口,并且重写run方法(创建一个任务,把任务分配给线程)

 实例化Runnable对象,利用Runnable对象去构建一个Thread对象

public class MyFirstTask implements Runnable{

    @Override
    public void run() {
        System.out.println("这是我的第一个任务的第一句话");
    }
}

public class Main {

    public static void main(String[] args) {
        MyFirstTask task = new MyFirstTask();
        //创建了一个任务对象
        Thread t = new Thread(task);

    }
}

3.启动线程

当手中有一个Thread对象时,调用其start()方法

注意:1.一个已经调用过start()不能再调用start()了,再调用就会有异常发生

           t.start()只允许工作在“新建”状态下

           2.千万不要调成run()

           调用run方法,就和线程没关系了,完全是在主线程中运行代码

 我们通过Thread对象控制线程的一切

Thread对象可以看做银行卡

JVM(HotSopt: 内部维护者关于线程的其他数据 ,看做一般商业银行

OS内部:实现java线程的OS线程的相关数据,看做中国人民银行


怎么理解t.start()做了什么?

把线程的状态从新建变成就绪状态,不负责分配CPU

线程把加入到线程调度器(不区分是OS还是JVM实现的)的就绪队列中,等待被调度器选中喷配CPU

从子线程进入到就绪队列的这一刻起,子线程和主线程在地位上就完全平等了,

但大概率是主线程,为什么?

主线程刚执行完t.start()就马上发生线程调度的概率不大,所以,大概率还是t.start()的下一条语句就先执行了。

什么时候子线程中的语句会先执行?

1.非常碰巧的在t.start()之后,sout之前,发生了一次线程调度

2.3.主线程的状态从运行变成就绪,主线程不再持有CPU,意味着主线程的下一条语句不再执行

调取时,选中子线程调度,子线程的状态从就绪变成运行

子线程池有了CPU,所以,执行到子线程的语句

 从此刻开始,我们的代码都是一样的,但是结果充满了随机性。

什么情况下会出现线程调度(开始一个新的线程分配CPU)?

参照web---2.系统_mmmenxj的博客-优快云博客进程的分区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值