众所周知,Java中有一些被称为是线程安全的集合容器,但是这里的线程安全会让人误以为在多线程环境中去使用这些容器就可以放心使用,包打天下。但是事实上并不是如此,在多线程中使用这些类仍然会存在问题。这就让人迷茫了,明明是线程安全的,为什么还会出错呢。我的理解是,明明是线程安全的,但是这些集合并不一定能在多线程环境中不出问题。
先看一段测试代码:public class VectorTest {
private static Vector testVector = new Vector();public static void main(String arg[]) {while (true) {for (int i = 0; i < 10; i++) {testVector.add(i);System.out.println("add" + i);}Thread remove = new Thread() {@Overridepublic void run() {try {for (int i = 0; i < testVector.size(); i++) {testVector.remove(i);System.out.println("remove" + i);Thread.sleep(1000);}} catch (Exception e) {e.printStackTrace();}}};Thread print = new Thread() {@Overridepublic void run() {try {for (int i = 0; i < testVector.size(); i++) {System.out.println(testVector.get(i));Thread.sleep(1000);}} catch (Exception e) {e.printStackTrace();}}};print.start();remove.start();while (Thread.activeCount() > 10) ;}

(这段代码是在看《深入理解java 虚拟机》这本书看到的)

 这段代码如果不运行可能看不出来问题,甚至运行了也不一定能暴露出问题,这里有一个很微妙的时机问题,等会儿具体分析。先看一下遇到的异常信息:

    这就是所谓的线程安全的类,在多线程中一样会有问题,那这是为什么呢,刚开始我也是百思不得姐,哦,是百思不得其解。后来在一篇博文当中看到了说Vector的contains方法和remove方法之前不具备原子性,这点给了提示。我现在认为出错的原因是在get和remove之间并没有在以上环境中做到同步,比方说,一个线程的get(2)操作发生时,正好遇到了remove操作的正在进行,这时get(2)这个操作就会阻塞,等待remove操作释放锁之后去操作。如果这时候remove操作的正好是remov(2)这个操作,等到去get的时候,这个元素已经没有了,get自然就只能是空欢喜一场。这里原因找到了,就该说解决办法了,在说解决办法之前,可能还会困惑,说好的线程安全呢,是不是童话里都是骗人的啊?我的理解是,线程安全并不代表使用安全,在实际使用时还是需要考虑当前环境中是否会出现问题的。那么问题来了,java提供线程安全的某些类的意义在哪里呢,反正还是会出问题。这就显得比较鸡肋了,但是也不能说没有意义,毕竟写程序还是要独立思考的。解决办法就比较简单了,在两个线程的run方法里加上synchronized (testVector),这样就会使得读取、删除线程中只会有一个对testVector进行操作,也就不会有上述情况出现。从这个错误来看的话,编程一定要谨慎,使用到的技术一定要深入了解,不能说不出问题,但是在出了问题之后能找出原因并解决,如果没有这个把握就不要轻易去使用,尤其在正式项目中,可能会让你欲哭无泪啊!

java Vector 在多线程使用中需要注意的问题相关推荐

  1. java面试(多线程)

    1. Callable.Future.FutureTash详解 Callable与Future是在JAVA的后续版本中引入进来的,Callable类似于Runnable接口,实现Callable接口的 ...

  2. 100道Java并发和多线程面试题

    1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓"知其然知其所以然","会用"只是 ...

  3. java基础学习-多线程笔记

    说说Java中实现多线程有几种方法 创建线程的常用三种方式: 1. 继承Thread类 2. 实现Runnable接口 3. 实现Callable接口( JDK1.5>= ) 4. 线程池方式创 ...

  4. 【手把手带你学Java EE】多线程那些事,你了解了吗?

    [手把手带你学Java EE]多线程那些事,你了解了吗? 线程 概念 意义 进程和线程的区别 面试题:谈谈进程和线程的区别和联系 Java中的多线程编程 创建线程的方法 方法一 方法二 方法三 &am ...

  5. Java进阶之多线程

    多线程 1>多线程基础 1.1.什么是线程?什么是进程? 1.2.Java程序中的进程与线程 1.3.线程与进程的关系 1.4.线程与线程的关系 1.5.单核CPU可以实现多线程并发吗? 2&g ...

  6. JAVA并发之多线程基础(2)

    除了我们经常用的synchronized关键字(结合Object的wait()和notify()使用)之外,还有对应的上篇文章讲到的方法JAVA并发之多线程基础(1)之外,我们日常中使用到最多的也就是 ...

  7. Java基础、多线程、JVM、集合八股文自述(持续更新)

    Java基础.多线程.JVM.集合八股文自述 一.Java基础 1.1 object类有哪些方法? getClass().hashCode().equals().clone().toString(). ...

  8. Java中的多线程编程(超详细总结)

    文章目录 Java中的多线程编程(超详细总结) 一.线程与多线程的概念 二.线程与进程之间的关系 三.一个线程的生命周期 四.多线程的目的和意义 五.线程的实现的方式 Java中的多线程编程(超详细总 ...

  9. Java回顾之多线程

    在这篇文章里,我们关注多线程.多线程是一个复杂的话题,包含了很多内容,这篇文章主要关注线程的基本属性.如何创建线程.线程的状态切换以及线程通信,我们把线程同步的话题留到下一篇文章中. 线程是操作系统运 ...

  10. Java基础之多线程详细分析

    在了解多线程之前,先来了解一下进程与线程之间的关系. 进程和线程: 进程是指在系统中正在执行的一个程序,每个进程之间是独立的. 线程是进程的一个基本执行单元.一个进程要想执行任务,必须得有线程(每1个 ...

最新文章

  1. linux 软件包的安装
  2. 百度爬虫爬到虚拟链接 网站被黑_网站地图sitemap对SEO优化有什么作用?
  3. ITK:从文件编写一个转换
  4. manually set focus for tag library
  5. 阮一峰:jQuery官方基础教程笔记
  6. 避免常见的6种HTML5错误用法,如何避免常见的6种HTML5错误用法
  7. PeekMessage
  8. command对象的获取 c#
  9. redis rdb aof区别_聊一聊RDB、AOF在redis持久化里的底层原理
  10. php 修改cache数据,修改ThinkPHP缓存为Memcache的方法
  11. 2021显著目标检测(SOD)方向部分论文汇总
  12. python第四章单元测试_MOOC选修课答案第四章单元测试答案_Sar编程基础期末答案...
  13. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_03 过滤器_2_FileNameFilter过滤器的使用和Lambda表达式...
  14. Excel数据透视表经典教程十三《打印数据透视表/图》
  15. web逻辑思维题目_逻辑思维训练500题以及答案
  16. meshlab点云颜色偏暗
  17. 用supermemo背单词达到5000词条
  18. 深度学习七:GAN和DCGAN入门
  19. 如何刷微博,怎么刷微博下拉框,怎样刷微博相关搜索
  20. java咖啡是研磨的吗_咖啡的研磨程度,真的很重要吗?

热门文章

  1. 为什么你学不过动态规划?告别动态规划,谈谈我的经验
  2. Google Earth Engine ——Landsat 8 影像集合Collection详细介绍
  3. 机器学习算法工程师--实习面经
  4. 短视频剪辑如何入门?给初学者的三个小建议,助你快速入门
  5. Intel HD Graphics620显卡不支持Windows7的驱动的间接安装显卡驱动
  6. 简单好用的洗鼻子方法?
  7. 解决Office2007安装时出现错误1706的方法(转载)
  8. 堆栈的存取原则是什么?
  9. VirtualBox 虚拟机安装黑群晖
  10. win10加入域环境