资讯专栏INFORMATION COLUMN

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

DevTTL / 2249人阅读

摘要:前言面试,必然要被问内存模型和并发开发。但是线程池启动多线程,是并发执行的。线程线程同时对值为的变量进行操作,结果返回,而不是。要不简单点,记住多线程对全局变量的写操作会发生冲突。

前言

面试Java,必然要被问Java内存模型和Java并发开发。我被问到的时候,心里慌得一批,“额,是在《Thinking in Java》里面写的吗?果然每天增删改太low了”

要了解这些图吗?

我希望能解释的再简单一些,以上都不用
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个线程卡死计算机。

内存模型,也说点简单的

栈(heap),函数加载的时候,为函数内部变量分配的空间。和父函数的内部变量和运行指针共享同一块区域。

函数运行时,new的空间,都是放在堆中的。

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

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

阅读更多

终于,我还是码造一个了中国地图

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

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108131.html

相关文章

  • Java并发面试幸亏有点道行不然又被忽悠

    摘要:前言面试,必然要被问内存模型和并发开发。但是线程池启动多线程,是并发执行的。线程线程同时对值为的变量进行操作,结果返回,而不是。要不简单点,记住多线程对全局变量的写操作会发生冲突。 前言 面试Java,必然要被问Java内存模型和Java并发开发。我被问到的时候,心里慌得一批,额,是在《Thinking in Java》里面写的吗?果然每天增删改太low了 要了解这些图吗? showI...

    jsbintask 评论0 收藏0
  • 漫画:程序员的“情人”节应该这样度过

    摘要:今天是年月号,一年一度的情人节又来了,今天对于很多年轻人来说是个特别的日子。该程序员在联谊会上认识了某艺术系女生,同乡的双方互有好感。 今天是2018年8月17号,一年一度的情人节又来了,今天对于很多年轻人来说是个特别的日子。但是作为屌丝界的一枚程序员,往往给人的印象是宅,不爱说话,智商不好,也不讨好哄女孩子欢心。但是,为什么我身边的程序员各个都是高智商,高颜值的小码农呢?或许,他们用...

    Shisui 评论0 收藏0
  • Android自定义权限使用总结

    摘要:使用场景自定义权限一般用于暴露出去的组件,提高安全性。拥有相同自定义权限的软件必须使用同样的签名,否则后一个程序无法安装。 最近在研究关于android自定义权限的问题,关于自定义权限一般是保证APP的安全性,那么什么事自定义权限?今天我们来补充一下自己的知识 作者:BrightVan地址:https://www.jianshu.com/p/b60... 1、如何声明自定义权限 在M...

    RobinQu 评论0 收藏0

发表评论

0条评论

DevTTL

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<