进程与线程+多线程优势

目录

⭐区别:

⭐进程的组织方式:

⭐线程概念及优势:

优势:

线程的创建:

⭐线程的创建方式:

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

⭐多线程的优势:


⭐区别:

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()方法(重点描述线程的定义+任务)

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()方法(重点描述线程任务)

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

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的子类

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接口。

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亿的操作,

单线程,串行执行任务;

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

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万后可以看到串行执行时间更短,效率更高

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爆更小哇

感谢鼓励,会一直加油~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值