谈谈多线程是否比串行快

起源

首先我们先绕开这个话题来聊一聊上下文切换路径,上下文切换路径可以顾名思义来理解就是不间断的分配CPU时间片来实现这个机制。时间片就是CPU分配给各个线程的时间因为时间片是非常的短暂,所以我们察觉不到,一般为几十毫秒

CPU通过时间片分配算法来循环各个线程的时间,当前任务执行一个时间片之后会切换到下一个任务,但是在切换之后会保存上一个任务的状态,以便下次在切换回来的时间,再次加载这个任务的状态,所以任务从保存到在加载的过程就是一次上下文切换

举一反三
就好比我们在看一本书,中途看到不懂得英文单词,这时我们需要去百度翻译查询是查询完之后还是要来看这本英文书,这个道理是与上下文切换一个道理,但是发现没有上下文切换的途中是不是消耗了时间去查阅我们的英文单词啊,这样对读书的效率是有影响的吧,所以说,同上!上下文切换也会影响多线程的
执行速度

测试

测试我们分别用1千、1万、10万、100万、1000万以及亿级别的数量来做测试,并且查看查出的时间差来对多线程与串行之间作为对比。具体为下列代码可查看。我这边就做1万与一亿来做测试,这样看来的对比会更直观。
一万数据量的查询

package demo1;

/**
 * @Author 藤井大叔
 * @Date 2021-09-17
 * @projectName 并发案例一
 * @description 并发与比串行之间的执行速度
 */
public class ContextDemo {

    private static final long count = 10000;

    /**
     * 并发案例
     * @throws InterruptedException
     */
    private static void comcurrency() throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int a = 0;
                for (long i = 0;i<count;i++){
                    a +=5;
                }
            }
        });
        thread.start();
        int b = 0;
        for (long i = 0;i<count;i++){
            b--;
        }
        thread.join();
        long time = System.currentTimeMillis() - start;
        System.out.println("并发查询时间为:"+time+"ms,数据量为:"+b);
    }

    /**
     * 串行案例
     */
    private static void serial(){
        long start = System.currentTimeMillis();
        int a = 0;
        for (long i = 0;i<count;i++){
            a+=5;
        }
        int b =0;
        for (long i=0;i<count;i++){
            b--;
        }
        long time = System.currentTimeMillis()-start;
        System.out.println("串行查询时间为:"+time+"ms,数据量为:"+b);
    }

    public static void main(String[] args) throws InterruptedException {
        comcurrency();
        serial();
    }
}

执行结果为:

并发查询时间为:2ms,数据量为:-10000
串行查询时间为:0ms,数据量为:-10000

在一万的数据量可发现并发执行的速度并非比串行快,下面在对亿级别的数据量做一个测试,我这边就不做代码而是直接将结果粘贴至下了,测试只需在上面的总数改下即可
亿级别数据量执行结果为:

并发查询时间为:45ms,数据量为:-100000000
串行查询时间为:76ms,数据量为:-100000000

在亿级别的数据量上确实多线程的执行速度要比串行快很多。下面我也分别对各个级别的做了相关测试。具体如下

数量级别并发(/ms)并行(/ms)
1千10
1万20
10万32
100万45
1000万1113
1亿4576

上面数据不为准确数据,因为是经过多次执行而选定的,不过大致认为如果说在并发执行不过百万级别的时候,当然并发还是要比串行慢的,为什么并发执行的会比串行慢呢?原因就是线程中有创建与上下文切换的开销,这也是需要时间成本的,所以在百万级以下的数据量并发还不如串行合适

防止方式

竟然已知耗时的原因就是出现在上下文切换上了,那么怎么去解决这个问题呢?这里有以下几种方案
无锁并发编程
无锁编发编程,多线程竞争锁时,会引起上下文切换,所以在多线程处理数据的时候,可以用一些办法来避免使用锁,如何将数据的ID按照Hash算法取模分段,不同的线程处理不同的段的数据

CAS算法
CAS算法,Java的Atomic包括使用CAS算法来更新数据,而不需要加锁

使用最少的线程
使用最少的线程,避免出现不需要的线程,比如任务量少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态

使用协议
在单线程中使用多任务的调度,并在单线程里维持多个任务间的切换

总结
若要前行,就要离开你现在停留的地方!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

藤井大叔

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值