cpu、进程、线程

概念

  并发编程的目的是让程序变得更快,同样的工作量,一个人忙活肯定没有两个人快,当然也是有前提的,简单介绍下概念

举个例子:

10瓶啤酒,1把起子,一个人只能用一把起子,打开1瓶啤酒1秒,10瓶10秒;

要是有两把起子呢,如果还是一个人,一个人只能用一把起子,起子再多也没用,还是10秒;

如果有两个人,两把起子呢,那一人拿一把起子,没人开5瓶,同时开,就只需要5秒;

将用人想成我们的程序,程序控制用几个人,一个人单线程,多个人多线程;将啤酒想成任务,需要达成的结果;将起子想成cpu核,开啤酒瓶需要起子,完成任务需要cpu来执行我们的程序,当起子够多,人够多,就能多人同时使用起子开啤酒;当cpu核数够多,线程开的够多,完成任务就快,理论如此,但看下面例子:

public class SpeedTest {

    /** 累加次数 */
    private static long count = 10000 * 10000 * 10;

    public static void main(String[] args) throws InterruptedException {
        //并行
        concurrent();
        //串行
        serial();
    }

    private static void concurrent() throws InterruptedException {
        Long start = System.currentTimeMillis();
        Thread thread = new Thread(() -> {
            long a = 0L;
            for (int i = 0; i < count; i++) {
                a += 1;
            }
            System.out.printf("concurrent, a=%s%n", a);
        });
        thread.start();

        long b = 0L;
        for (int i = 0; i < count; i++) {
            b += 1;
        }
        thread.join();
        Long end = System.currentTimeMillis();
        System.out.printf("concurrent, b=%s, count=%s, time=%sms%n", b, count, end - start);
    }

    /**
     * 串行
     */
    private static void serial() {
        long a = 0L;
        long b = 0L;
        Long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            a += 1;
        }
        System.out.printf("serial, a=%s%n", a);
        for (int i = 0; i < count; i++) {
            b += 1;
        }
        Long end = System.currentTimeMillis();
        System.out.printf("serial, b=%s, count=%s, time=%sms%n", b, count, end - start);
    }
}

  不同count下的耗时:

Connected to the target VM, address: '127.0.0.1:51419', transport: 'socket'
concurrent, b=100000000, count=100000000, time=127ms
serial, b=100000000, count=100000000, time=90ms
Disconnected from the target VM, address: '127.0.0.1:51419', transport: 'socket'  
Connected to the target VM, address: '127.0.0.1:51369', transport: 'socket'
concurrent, b=1000000000, count=1000000000, time=527ms
serial, b=1000000000, count=1000000000, time=852ms
Disconnected from the target VM, address: '127.0.0.1:51369', transport: 'socket'

  如此,count = 1亿时,还是串行快的。

cpu时间片分配

  仔细想下,当只有一把起子的时候,就不能有多个人吗?当然可以,起子可以轮着用,你开一瓶啤酒,再给我开一瓶啤酒,类比cpu,当只有单核cpu时,多个线程是先给你执行下,在给我执行下,交换的来,这叫cpu时间片分配;

上下文切换

  按一定的算法给每个线程分配时间;再来比如我起瓶盖刚起一半,起子就交给了你,甭管你咋用,再次到我手上的时候,我就不会重新起了,因为我给你起子时已经记录下了正在起的是哪一瓶,瓶盖上哪个位置,直接从上次的位置开始起,很严谨,类比cpu,当  cpu时间结束时,会记录该线程当任务状态,当cpu再次轮询到该线程时,直接从上次结束的位置接着执行,这里任务状态从保存到再次加载的过程就叫cpu的一次上下文切换;这里就能发现,多线程不一定快,因为上下文切换也需要时间,资源不够时,线程开再多,反而会更慢

线程、进程

  再来比如现在有一间屋子里一帮人在开啤酒瓶,隔壁屋子一帮人在开可乐,就一把起子,起子就这样两屋子递来递去,这就是单核cpu在执行两个进程的程序,里面的人就是线程,所以,一个进程可以有多个线程,线程是进程里的,因为cpu运转非常快,每个时间片毫秒级别,所以即使单核cpu也能同时兼顾多个程序,并感觉不出来。

posted @ 2022-01-09 23:53  MonkeyJesus  阅读(180)  评论(0)    收藏  举报