并发 十六 不要使用Thread join ——并行变串行

首先给大家分享一个巨牛巨牛的人工智能教程,是我无意中发现的。教程不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵段子,像看小说一样,哈哈~我正在学习中,觉得太牛了,所以分享给大家!点这里可以跳转到教程

                    

在多线程程序的编写中,为了同步线程的执行状态,我们为了方便,经常会使用Thread.join()方法,须不知此方法有重大的性能缺陷,能将多线程程序变成单线程程序,执行时间瞬间翻倍,示例如下:

/** *  用于长时间的任务计算,一般求fabic(40)就会花费1秒的时间 *  花费时间呈指数增长速度 */static long fabic(int n) {    if(n < 0) {        throw new NumberFormatException("不能小于0");    }    if(n == 1 || n == 2) {        return 1;    }    return fabic(n - 1) + fabic(n - 2);}public static void main(String[] args) throws InterruptedException {    long startTime = System.currentTimeMillis();    int NUM = 3;    for(int i = 0; i < NUM; i ++) {        //  创建线程        Thread th = new Thread(() -> {            fabic(35 + i);        });        th.start();        th.join();    }    //  打印花费的时间    System.out.println(System.currentTimeMillis() - startTime);}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

通过监测应用程序的执行时间,或者在线程内添加调试日志,我们发现,现在三个线程会依次执行,即线程0执行完了才执行线程1,类似于连续调用了3次th.run()方法(其实效率更低,因为还有线程创建、切换、销毁的时间)。

在上述的代码测试中,我们还发现了一个令人惊讶的现象,调用fabic的递归函数,JAVA的执行时间竟然超过Python 100多倍,下面是成绩对比:

                       
斐波那契数NJAVA(ms)Python(ms)结果
353129919227465
4036233533102334155

当然用递归求斐波那契数的方法绝对不是一种高效的方法,但能否说明Python对递归优化得不够,还是Python对栈桢的设计策略存在问题?更高效的求斐波那契数的方法如下:

#   用公式求导更快def fabic(n):    if(n < 1):        raise Exception('the argument can not less than 0')    #   辅助数组    result = [0, 1, 1]    if(n < 2):        return 1    while(n > 2):        result.pop(0)        result.append(result[0] + result[1])        n = n - 1    else:        return result[2]
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

所以,除了在调试环境中,可以执行Thread.join()方法,否则还不如不要启动线程,直接执行方法调用,正确的方法是应该使用CountDownLatch、CyclicBarrier这样的线程工具,如下:

static class FabicTask implements Runnable {    private int num;    private final CyclicBarrier barrier;    public FabicTask(int num, CyclicBarrier barrier) {        super();        this.num = num;        this.barrier = barrier;    }    public void run() {                 fabic(num);        try {            //  发信号等待结束            this.barrier.await();        } catch (InterruptedException e) {            e.printStackTrace();        } catch (BrokenBarrierException e) {            e.printStackTrace();        }    }}public static void main(String[] args) throws InterruptedException {    int NUM = 3;    long startTime = System.currentTimeMillis();    CyclicBarrier barrier = new CyclicBarrier(NUM, () -> {        //  计算耗费时间        System.out.println(System.currentTimeMillis() - startTime);     });    for(int i = 0; i < NUM; i ++) {        new Thread(new FabicTask(41, barrier)).start();    }}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

结论

不要再生产环境中使用Thread.join()方法。

           

浏览人工智能教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值