Java并发口试,幸而有点道行,不然又被忽悠了

2019-08-22 00:00:00 口试 道行 幸而

媒介

口试Java,必定要被问Java内存模子和Java并发开辟。我被问到的时刻,内心慌得一批,“额,是在《Thinking in Java》内里写的吗?果真天天增编削太low了”

要相识这些图吗?

《Java并发口试,幸而有点道行,不然又被忽悠了》

《Java并发口试,幸而有点道行,不然又被忽悠了》

《Java并发口试,幸而有点道行,不然又被忽悠了》

《Java并发口试,幸而有点道行,不然又被忽悠了》

我希望能诠释的再简朴一些,以上都不必

Java 并发代码
public class Example1 {
    public static int count = 0;
    public static int clientTotal = 5000;
    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < clientTotal ; i++) {
            executorService.execute(() -> {
                try {
                    add();
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
    }
    private static void add() {
        count++;
    }
}

假如上面代码实行,count的值是多少?(为了申明重点题目,没有写末了打印的代码)
5000?屡次运转的效果,count的值是小于5000的。

诠释一下上面的顺序,起首定义了一个线程池,启动5000个线程实行add()操纵,add函数处置惩罚静态成员变量count。

假如顺序顺序调用,count的值应该是5000。

for(int i=0;i<5000;i++){
    add();
}

然则线程池启动多线程,是并发实行的。每一个线程启动以后,不论是不是运转完毕,下一个线程会立时启动。

启动线程的历程,是一个异步历程,启动线程马上返回,启动下一个历程。

当多个线程对统一个变量add举行操纵的时刻,就会发作写写争执。

线程1、线程2 同时对值为0的变量举行操纵,效果返回1,而不是2。假如这个处所想不明白,就请留言,或许看看文章顶部那些原理图。

要不简朴点,记着“多线程对全局变量的写操纵会发作争执”。

答案,声明原子变量 AtomicInteger count

public class CountExample2 {

    // 要求总数
    public static int clientTotal = 5000;

    // 同时并发实行的线程数
    public static int threadTotal = 200;

    public static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal ; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                    log.error("exception", e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.info("count:{}", count.get());
    }
    private static void add() {
        count.incrementAndGet();
        // count.getAndIncrement();
    }
}

注,上面的代码用了天生者消费者形式,5000个生产者,200个消费者,对顺序并发做肯定限定,防备5000个线程卡死计算机。

内存模子,也说点简朴的

    1. 栈(heap),函数加载的时刻,为函数内部变量分派的空间。和父函数的内部变量和运转指针同享统一块地区。
    1. 函数运转时,new的空间,都是放在堆中的。

这个就是C的内存模子,做shellcode的基础知识。

作者:白头雁
链接:https://www.jianshu.com/p/8cb…

浏览更多

终究,我照样码造一个了中国地图

SVG前戏—让你的View多姿多彩

分享几个Android很强势的的开源框架

(Android)口试题级答案(精选版)

    原文作者:爱编码的coder
    原文地址: https://segmentfault.com/a/1190000015999606
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章