前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >进程与线程+多线程优势

进程与线程+多线程优势

作者头像
用户11162265
发布2024-11-20 14:26:21
发布2024-11-20 14:26:21
9000
代码可运行
举报
文章被收录于专栏:C语言C语言
运行总次数:0
代码可运行

⭐区别:

1、进程中包含线程,每一个进程都至少一个线程(主线程)

2、进程是申请系统资源的最小单位

3、线程是CPU调度的最小单位

4、进程之间不能共享资源,但同一进程中的线程之间共享进程申请的系统资源

5、一个线程崩溃了会影响整个进程

6、线程的创建、销毁、调度效率比进程更高,并且有自己独立的执行任务。

⭐进程的组织方式:

通过一个双向链表来组织PCB:

创建一个进程就是把PCB加入到链表中;

销毁一个进程就是把PCB从链表中删除;

查看所有的进程就是遍历双向链表。

⭐线程概念及优势:

多进程能充分利用CPU资源去处理复杂业务,从而提高效率。

但是进程申请资源对系统的性能影响较大,涉及内存和文件资源,处理一个事情有一份资源就够了。

线程用的就是进程启动时从操作系统中分配的资源,(线程也可以叫轻量级的进程),当创建一个进程时,进程中就会包含一个线程,叫主线程。

我们可以理解为进程就是一个公司,线程就是员工,一个公司可以有多个员工,一个进程可以创建多个线程。

优势:

创建速度比进程快;

销毁速度比进程快;

线程的CPU调度速度比进程快。

线程的创建:

创建线程的个数,根据CPU逻辑处理器数量来作为参考

通过多线程的方式可以提高效率,但当线程数量大于逻辑处理器数时,由于过多线程处于阻塞等待状态,不能真正发挥作用,反而因创建线程消耗系统资源。

当某一个线程出现问题,会影响其他线程,进而影响整个进程。

一个线程崩溃会导致整个进程崩溃。

线程的执行顺序:

线程的执行顺序没有规律,这个和CPU调度有关。

而CPU调度是“抢占式”执行的,所以哪个线程当前占用CPU资源是不清楚的。

⭐线程的创建方式:

操作系统提供了一些API(应用程序接口)供程序员使用,Java对不同操作系统的API进行了封装

在JAVA中Thread类用来描述一个线程,创建的每个线程都是Thread类的对象

1、继承Thread类(线程对象),重写run()方法(重点描述线程的定义+任务)

代码语言:javascript
代码运行次数:0
复制
public class Demo {
    public static void main(String[] args) {
        //线程的多种创建方式

        //通过继承Thread类并重写run方法
        MyThread t1 = new MyThread();
    }
}

class MyThread extends Thread{
    @Override
    public void run(){
        System.out.println("hello my Thread");
    }
}

2、实现Runnable接口,重写run()方法(重点描述线程任务)

多个线程执行同一个任务推荐用这种方式。

代码语言:javascript
代码运行次数:0
复制
public class Demo_206 {
    public static void main(String[] args) {
        //线程的多种创建方式

          //通过Runnable示例来单独定义线程的任务对象
        MyRunnable r1 = new MyRunnable();
        Thread thread = new Thread(r1);
    }
}
class MyRunnable implements Runnable{
    @Override
    public void run(){
        System.out.println("hello my Runnable");
    }
}

更推荐第二种

简化的方式:

通过匿名内部类的方式,创建Thread的子类,Runnable的子类

代码语言:javascript
代码运行次数:0
复制
public class Demo_206 {
    public static void main(String[] args) {
        //线程的多种创建方式

        //通过创建Thread匿名内部类的方式创建线程
        Thread thread1 = new Thread(){
            @Override
            public void run(){
                System.out.println("通过Thread匿名内部类的方式创建线程");
            }
        };

        //匿名内部类,Runnable
        Thread thread2 = new Thread(new Runnable(){
            @Override
            public void run(){
                System.out.println("匿名内部类,Runnable……");
            }
        });

    }
}

通过Lambda表达式的方式,简洁方便

由于Runnable接口是一个函数式接口(接口中只定义的有一个方法),可以通过lambda表达式的方式创建,本质上就是实现了Runnable接口。

代码语言:javascript
代码运行次数:0
复制
public class Demo_206 {
    public static void main(String[] args) {
        //线程的多种创建方式

        //通过Lambda表达式创建一个线程
        Thread thread3 = new Thread(()->{
            System.out.println("通过Lambda表达式创建线程……");
        });
    }
}

⭐Thread类的start()方法和run()方法的区别:

start方法能真实的申请系统进程PCB,从而启动一个线程执行任务,参与CPU调度。

PCB与Thread对象一 一对应,但所处环境不同,生命周期不同。

Java中创建一个线程对象——>调用start()方法启动线程对象——>JVM调用系统的API——>生成PCB,创建系统中的线程——>参与CPU调度

run方法只是Java对象的一个普通方法,定义了线程要执行的任务,但是调用run方法不会申请系统进程PCB,不能启动线程。

⭐多线程的优势:

能够增加运行速度。

通俗讲,

一个大的任务来分配给多个执行者来一起执行就会更快完成任务,进而提高效率;


设置一个场景,执行两次自增到10亿的操作,

单线程,串行执行任务;

多线程,这里设置两个线程,两个线程分别执行;

代码语言:javascript
代码运行次数:0
复制
public class Demo {
    //大数可以使用分隔符_
    private static long count = 10_0000_0000l;
    public static void main(String[] args) {
        //串行
        serial();
        //并行
        concurrency();
    }
    private static void concurrency(){
        //记录开始时间
        long begin = System.currentTimeMillis();
        //创建两个线程,各自累加
        Thread t1 = new Thread(()->{
                long a = 0l;
                for(int i = 0; i < count; i++){
                    a++;
                }
        });
        t1.start();//启动线程
        Thread t2 = new Thread(()->{
            long b = 0l;
            for(int i = 0; i < count; i++){
                b++;
            }
        });
        t2.start();//启动线程
        long end = System.currentTimeMillis();

        System.out.println("并行执行时间:"+ (end - begin));
        
    }
    private static void serial(){
        //记录开始时间
        long begin = System.currentTimeMillis();
        long a = 0l;
        for(int i = 0; i < count; i++){
            a++;
        }
        long b = 0l;
        for(int i = 0; i < count; i++){
            b++;
        }
        //记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("串行执行时间:" + (end - begin));
    }
}

结果:

我们可以看到并行执行时间快很多,但是这并不是真的并行执行时间,

开始记录时间后创建了线程t1,然后开启t1,接着创建线程t2并开启该线程,然后就打印了执行时间,但此时两个线程还在执行任务,没有结束。

要想打印出真正的并行执行时间,可以让线程调用join()方法,哪个线程调用join方法,主线程就要等待该线程执行完它的任务

所以我们能够看出通过多线程的方式能够提高效率,并行的执行时间是串行的一半多一点,之所以多一点是由于创建线程还会耗时。

但并不是多线程的效率都比单线程高,当任务量很少时,由于多线程创建会耗时,单线程效率可能更高。

当把10亿换成5万后可以看到串行执行时间更短,效率更高

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ⭐区别:
  • ⭐进程的组织方式:
  • ⭐线程概念及优势:
    • 优势:
    • 线程的创建:
  • 线程的执行顺序:
  • ⭐线程的创建方式:
  • ⭐Thread类的start()方法和run()方法的区别:
  • ⭐多线程的优势:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档