java多线程 arrayList线程安全和不安全

image.png

从上图可以看见Vector这个和ArrayList的源码很类似 都有一个Object数组 但是Vector里面有个synchronized修饰符 这个稍后理解
为了理解线程安全和不安全,我们需要对java里面的多线程做一个了解
首先介绍一个工具 是jdk自带的一个工具 通过这个工具可以很方便的看我们的应用程序里面的内存情况 ,cpu情况以及线程情况
首先在MyIndex里写入如下代码
使当前线程休眠100000毫秒 因为不休眠我们运行时程序一闪而过看不出效果


image.png

这时在我们编辑器里代码标红 alt+enter 选中第一项
在我们的main函数上加上了如下代码


image.png

即 throws InterruptedException
接下来先看下工具
image.png

在终端中输入Jvisualvm回车
出现如下界面
image.png

可以看见Visualvm和idea都在监控范围内 由于我们程序没有运行 所以看不见任何信息

接下来运行一下程序


image.png

可以看见我们多了运行程序的信息 看见了线程处MyIndex处于休眠状态
接下来我们学习下多线程是什么 关键部分如何编码 以及一旦我们进到多线程情况下 为什么Vector是线程安全的 ArrayList是线程不安全的
多线程编码
image.png

我们要实现多线程运行都要使用到Thread类 Thread类继承了runaable接口 里面有一个run方法是必须要实现的
所以我们可以猜出要么我们继承Thread类要么继承runnable接口 但是我们运行线程的时候必须使用Thread
接下来我们写一种常见的方式
在Core中创建一个java文件叫MyThread
在这个文件中我们继承Runaable接口实现run方法
代码如下
image.png

接下来来到MyIndex文件创建一个线程
image.png

以上代码就是创建一个线程 但是函数没有传入任何参数 没有任何意义
所以我们需要传入参数 但是参数传什么呢?
其实只要传入实现于Runnable接口的实现类就可以了
这里有两种方法
1.可以直接在MyIndex里面写入如下 如果业务比较简单 我们可以直接用内部类 new接口的形式实现
image.png

2.如果我们想独立的封装一些业务 也可以传入刚刚创建的MyThread类的实例对象


image.png

接下来演示下开5个线程分别执行一些事情
如何去执行呢?需要在run方法里写一些代码
image.png

运行结果
image.png

出现5个abc 这是由5个线程同时执行的 其实在cpu执行过程中也是有一些时间差的
以上即为多线程最简单的代码
下面我们来学习一线线程安全和不安全
首先创建个List
image.png

所谓的线程不安全 就是我们在执行的时候我们需要将ArrayList放入子线程中去执行 如果程序运行时只有一个线程 那么线程安全和不安全没什么区别 都是安全的 因为只有一个线程
接下来我们在执行的过程中将mylist传给子线程 让子线程去执行
这时我们需要对java按值传递还是引用传递有一些了解
我们将mylist传给子线程MyThread 在子线程或者方法中对mylist做一些修改 会影响原有的mylist 如果传递基本数据类型则不会
接下来如何传呢?
我们在MyThread里写入如下
image.png

然后再MyIndex里面子线程接收mylist参数
image.png

运行结果
image.png

image.png

点击多次运行结果不相同 这时我们的线程出现不安全的情况了
我们将MyThread里循环次数加大到200
代码如下
image.png

运行结果
同样出现线程不安全情况
同样我们可以给我们的线程命名看是哪个线程引起的问题
image.png

以上即为多线程对对象操作的时候产生的问题。这里最关键的问题是ArrayList里的add方法
会出现线程不安全是因为有可能执行一个线程的时候另外一个线程进入将值覆盖 或者进行插入操作 产生数组越界
为什么说Vector是线程安全的呢?
这是我们将MyIndex代码改为如下
image.png

MyThread代码 将循环次数加大到500
image.png

运行结果
image.png

运行多次 发现结果也不一样 但是比起ArrayList是不出现数组越界的错误了

但是结果为什么会不一样呢?
有可能我们的子线程没执行完就将输出结果打印出来了。
那么我们如何解决子线程执行完在执行主线程呢?


image.png

接下来演示一下代码
把上面的五个线程放入一个List集合里 这里我们写ArrayList是没有问题的 因为我们的代码没有变成多线程
这几句都是在主线程中执行的 不存在线程不安全
image.png

运行结果
image.png

不管运行多少次 结果都为2500 这是因为我们的输出结果在子线程执行结束后才运行的
是因为Vector源码的实现中有synchronized符 表示的是同步的 必须执行完才能执行别的进程
以上代码是用Vector接口实现的
但是我们如果就想用ArrayList怎么办呢?
这时我们要借助之前学习的工具类Collections(集合)来产生一个同步的ArrayList
image.png

运行结果
image.png

多次运行都是2500 上面改成同步List只是解决线程安全的一种方法

你可能感兴趣的:(java多线程 arrayList线程安全和不安全)