多线程 - 01 之 多线程编程一定快嘛?


在面试中经常被问到多线程一定比单线程快嘛?希望看完这篇文章你可以后一个很好的答案

运行测试

我们使用下面这段代码测试一下多线程和单线程的运行速度,代码来源—java并发编程的艺术

private static final long count = 100000000L;
    public static void main(String[] args) throws InterruptedException {
        concurrency();
        serial();
    }
    private static void concurrency() 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--;
        }
        long time = System.currentTimeMillis() - start;
        thread.join();
        System.out.println("concurrency :" + time+"ms,b="+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("serial:" + time+"ms,b="+b+",a="+a);
    }

测试结果

不同机器结果可能存在不同,但是规律相同

计算次数多线程计算时间(ms)单线程计算时间(ms)
1060
100040
1万10
10万62
1000万70295
1亿84282

从测试结果可以看出多线程在计算量逐渐变大之后优势逐渐显示了处理,但是在较少的计算量情况下甚至还不如单线程的计算时间,
那么为什么会出现这种情况的?

原因

上下文切换

即使是单核处理器也支持多线程处理代码,CPU 是通过给每个线程分配时间片的方式实现这个机制,这个机制叫做
并发执行机制原理:简单地说就是把一个处理器划分为若干个短的时间片,每个时间片依次轮流地执行处理各个应用程序,由于一个时间片很短,相对于一个应用程序来说,就好像是处理器在为自己单独服务一样,从而达到多个应用程序在同时进行的效果 。
时间片一般是几十毫秒左右。
CPU通过时间片分配算法来循环执行任务,当前任务时间片执行完毕之后会去执行下一个任务,但是在切换的过程中会保存上一个任务的执行状态,可以再加载这个线程的状态,所以任务从保存到再加载就是一次上下文切换。
频繁的上下文切换也会影响程序的执行效率。
我们假设一个任务的计算量是 1
那么 两个线程的计算量近似等于 二分之一 加上 上下文切换时间乘次数
当上下文切换时间乘次数 大于 计算量的 二分之一时,双线程的效率就不会很高

如何有效的避免上下文切换

  1. 无锁并发编程:当多线程竞争锁时,会引起上下文切换,可以使用一些方式来避免锁的使用锁,比如说把一个任务分割成多段小任务,每个线程执行固定的一段,比如说:ConcurrentHashMap的扩容机制,fork/join 框架。
  2. cas算法 : java的Atomic包使用cas算法更新数据,而不需要加锁,从而减少上下文切换
  3. 使用最少线程:防止大量线程处于等待状态
  4. 协程:单线程里实现多任务的调度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

1999

每人一点点,明天会更好

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

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

打赏作者

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

抵扣说明:

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

余额充值