博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java并发面试,幸亏有点道行,不然又被忽悠了
阅读量:6206 次
发布时间:2019-06-21

本文共 2395 字,大约阅读时间需要 7 分钟。

前言

面试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个线程卡死计算机。

内存模型,也说点简单的

    1. 栈(heap),函数加载的时候,为函数内部变量分配的空间。和父函数的内部变量和运行指针共享同一块区域。
    1. 函数运行时,new的空间,都是放在堆中的。

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

作者:白头雁 链接:

阅读更多

转载地址:http://lmqca.baihongyu.com/

你可能感兴趣的文章
let与expr命令的用法与实战案例
查看>>
log日志轮转--logrotate
查看>>
创建邮箱过程中的问题及解决办法
查看>>
函数式编程概念
查看>>
安装输入发
查看>>
用户配置相关文件
查看>>
Django开发中常用的命令总结
查看>>
thinkphp实现分页
查看>>
自动化运维之saltstack(二)states深入理解
查看>>
变量拼接的四种方法
查看>>
expect 批量修改服务器用户密码
查看>>
linux下配置SS5(SOCK5)代理服务
查看>>
Nginx平滑升级到最新版本
查看>>
Python自动化运维:Django之View视图和Template
查看>>
hive配置
查看>>
Oracle Controlfile控制文件中记录的信息片段sections
查看>>
菜鸟也学hadoop(1)_搭建单节点的hadoop
查看>>
spanning-tree extend system-id
查看>>
思维导图分析http之http协议版本
查看>>
linux延时与定时操作
查看>>