请简要说明java中线程安全是怎么回事?
比如说,两个线程操作同一个ArrayList变量,那么一个线程这一时刻读的数据可能在下一刻要改变。
一般在类似于下面的情景下考虑线程安全的问题:
ArrayList products=new ArrayList ();
products用来存放生产出来的产品。
现在假设:有3个消费者线程,2个生产者线程。
每个生产者线程生产出一个产品,执行
products.add(new Product());
每个消费者线程消费一个产品执行
if(products.size()>=1){ products.remove(0);}
如果products里现在只有一个产品可以消费,但是有2个消费者线程请求消费,那么就有可能出现一个产品被同时消费的问题,而这是和实际不符的。
但是不同的线程访问Vector的时候不会发生这种错误,因为java会有相应的机制是同一时刻只有一个线程对这个变量操作。
这就是所谓的:
Vector:是线程安全的
ArrayList:不是线程安全的
你问的是java API中的哪些类是安全的?还是线程安全的意思?关于线程安全,是指当多个线程访问同一个变量时,该变量不会因为多线程访问产生意想不到的问题,为了避免多线程访问的不可预知的问题,对于程序中多线程能访问到的变量要加锁,即加synchronized,放在同步块中,或者对改变该变量值的方法加synchronized限制。当然jdk中自带的一些类本身就实现了该机制,本身就是线程安全的,比如StringBuffer,Vector等。多线程是程序中比较高级的一个方面,希望你能深入理解!
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。
编辑本段线程安全性 类要成为线程安全的,首先必须在单线程环境中有正确的行为。如果一个类实现正确(这是说它符合规格说明的另一种方式),那么没有一种对这个类的对象的操作序列(读或者写公共字段以及调用公共方法)可以让对象处于无效状态,观察到对象处于无效状态、或者违反类的任何不可变量、前置条件或者后置条件的情况。
此外,一个类要成为线程安全的,在被多个线程访问时,不管运行时环境执行这些线程有什么样的时序安排或者交错,它必须仍然有如上所述的正确行为,并且在调用的代码中没有任何额外的同步。其效果就是,在所有线程看来,对于线程安全对象的操作是以固定的、全局一致的顺序发生的。
正确性与线程安全性之间的关系非常类似于在描述 ACID(原子性、一致性、独立性和持久性)事务时使用的一致性与独立性之间的关系:从特定线程的角度看,由不同线程所执行的对象操作是先后(虽然顺序不定)而不是并行执行的。
线程安全性不是一个非真即假的命题。 Vector 的方法都是同步的,并且 Vector 明确地设计为在多线程环境中工作。但是它的线程安全性是有限制的,即在某些方法之间有状态依赖(类似地,如果在迭代过程中 Vector 被其他线程修改,那么由 Vector.iterator() 返回的 iterator会抛出ConcurrentModifiicationException)。
对于 Java 类中常见的线程安全性级别,没有一种分类系统可被广泛接受,不过重要的是在编写类时尽量记录下它们的线程安全行为。
Bloch 给出了描述五类线程安全性的分类方法:不可变、线程安全、有条件线程安全、线程兼容和线程对立。只要明确地记录下线程安全特性,那么您是否使用这种系统都没关系。这种系统有其局限性 -- 各类之间的界线不是百分之百地明确,而且有些情况它没照顾到 -- 但是这套系统是一个很好的起点。这种分类系统的核心是调用者是否可以或者必须用外部同步包围操作(或者一系列操作)。下面几节分别描述了线程安全性的这五种类别。不可变 不可变的对象一定是线程安全的,并且永远也不需要额外的同步[1]。因为一个不可变的对象只要构建正确,其外部可见状态永远也不会改变,永远也不会看到它处于不一致的状态。Java 类库中大多数基本数值类如 Integer 、 String 和 BigInteger 都是不可变的。线程安全 线程安全的对象具有在上面“线程安全”一节中描述的属性 -- 由类的规格说明所规定的约束在对象被多个线程访问时仍然有效,不管运行时环境如何排列,线程都不需要任何额外的同步。这种线程安全性保证是很严格的 -- 许多类,如 Hashtable 或者 Vector 都不能满足这种严格的定义。有条件的线程安全 有条件的线程安全类对于单独的操作可以是线程安全的,但是某些操作序列可能需要外部同步。条件线程安全的最常见的例子是遍历由 Hashtable 或者 Vector 或者返回的迭代器 -- 由这些类返回的 fail-fast 迭代器假定在迭代器进行遍历的时候底层集合不会有变化。为了保证其他线程不会在遍历的时候改变集合,进行迭代的线程应该确保它是独占性地访问集合以实现遍历的完整性。通常,独占性的访问是由对锁的同步保证的 -- 并且类的文档应该说明是哪个锁(通常是对象的内部监视器(intrinsic monitor))。
如果对一个有条件线程安全类进行记录,那么您应该不仅要记录它是有条件线程安全的,而且还要记录必须防止哪些操作序列的并发访问。用户可以合理地假设其他操作序列不需要任何额外的同步。线程兼容 线程兼容类不是线程安全的,但是可以通过正确使用同步而在并发环境中安全地使用。这可能意味着用一个 synchronized 块包围每一个方法调用,或者创建一个包装器对象,其中每一个方法都是同步的(就像 Collections.synchronizedList() 一样)。也可能意味着用 synchronized 块包围某些操作序列。为了最大程度地利用线程兼容类,如果所有调用都使用同一个块,那么就不应该要求调用者对该块同步。这样做会使线程兼容的对象作为变量实例包含在其他线程安全的对象中,从而可以利用其所有者对象的同步。
许多常见的类是线程兼容的,如集合类 ArrayList 和 HashMap 、 java.text.SimpleDateFormat 、或者 JDBC 类 Connection 和 ResultSet 。线程对立 线程对立类是那些不管是否调用了外部同步都不能在并发使用时安全地呈现的类。线程对立很少见,当类修改静态数据,而静态数据会影响在其他线程中执行的其他类的行为,这时通常会出现线程对立。线程对立类的一个例子是调用 System.setOut() 的类。
java中的包是什么概念?详细说明。谢谢
一、为什么java中要有"包"的概念?以一言概之,java中"包"的引入的主要原因是java本身跨平台特性的需求。因为java中的所有的资源也是以文件方式组织,这其中主要包含大量的类文件需要组织管理。java中同样采用了目录树形结构。虽然各种常见操作系统平台对文件的管理都是以目录树的形式的组织,但是它们对目录...
请简要说明Java基于SWING的图形用户界面设计中的事件机制及处理事件的步...
Java采用的是推模式,所有监听事件都基于观察者设计模式,所以我们也可以自己给予观察者开发出专用的监听器。我们JavaGUI程序开发,会经常使用到监听事件,比如一个小计算器的程序,当我们点击“计算”按钮后,希望程序将两个文本框中的数字相加,那么就必需给这个按钮添加事件:1)按钮的动作触发事件接口是...
谁能通俗的解释一下java中clone!并说明如何使用!
深复制就是不仅复制了对象本身(成员变量分成两块 一块是基本类型 一块是对象) 不仅复制了基本类型的值 同时也复制了成员变量中的对象 也就是new出来新的对象并设置和被克隆方法一样的值 如果成员变量存在对象 继续按此方法复制 此时复制出新对象的引用指向了新的对象 两者完全是独立的 改变一个不影响...
JAVA中局部内部类和匿名内部类的特点和作用?最好能详细说明,谢谢各位...
Java 内部类 分四种:成员内部类、局部内部类、静态内部类和匿名内部类。 1、成员内部类: 即作为外部类的一个成员存在,与外部类的属性、方法并列。注意:成员内部类中不能定义静态变量,但可以访问外部类的所有成员。public class Outer{private static int i = 1;private int j=10;private int k=20;public stat...
什么是继承,试说明在java中实现多继承的方法
2.JAVA中没有多继承,而用接口实现了多继承!一个类或是可以同时实现多个接口!(就相当于C++里一个类同时继承了多个类!)例如:public class Son implements Father1,Father2,Father3{ } 接口有利于代码功能的扩展(增加新的功能)!而继承则有利于代码功能的修改(把旧的功能改成新的功能)!这里...
Java中常用的设计模式有哪些?请详细说明一下工厂模式。
1.单例模式(有的书上说叫单态模式其实都一样)该模式主要目的是使内存中保持1个对象 2.工厂模式 该模式主要功能是统一提供实例对象的引用。看下面的例子:public class Factory{ public ClassesDao getClassesDao(){ ClassesDao cd = new ClassesDaoImpl();return cd;} } interface ClassesDao{ pu...
java中static的具体作用是什么 ?举例说明
这里,classname 是类的名字,在该类中定义static方法。可以看到,这种格式与通过对象引用变量调用非static方法的格式类似。一个static变量可以以同样的格式来访问——类名加点号运算符。这就是Java 如何实现全局功能和全局变量的一个控制版本。下面是一个例子。在main() 中,static方法callme() 和static ...
java简单叙述什么是访问控制符,列出JAVA中的访问控制符,并说明各个访问...
public:任何代码都可以访问。protected:只有子类和同包内的代码可以访问。默认访问权限:没有关键字,同一包内代码可以访问。private:只有本类内部可以访问。
JAVA中的重载、覆盖和继承搞不清楚,麻烦就例简要说明
第8题,D.重载的标志是:1.首先,函数名要一样(题目中都是add)2.在1的基础下,至少要符合下列条件之一(可符合多种)(1)参数列表不同。(这里的参数列表,即函数接收的参数的列表,而同与不同再关参数的类型与参数的多少,至于参数的名称,根本不重要,以下举例 a. (int a, int b)与(...
Java中字母大小写有什么区别?
Java是一种区分字母的大小写(case-sensitive)的语言,下面举例说明Java语言中包、类、变量等的命名规范。(一)Package(包)的命名:Package的名字应该都是由一个小写单词组成,例如net.ebseries.modules。(二)Class(类)的命名:Class的名字首字母大写,通常由多个单词合成一个类名,要求每个单词的首字母也...
窄菲美珞: 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的.或者说:一个类或者程序所提供的接口...
樟树市18613215211: Java中线程安全是什么??
窄菲美珞:就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问高淇Java300集视频教程对线程安全有详细的讲解.
樟树市18613215211: JAVA中线程安全的map有哪些? - ?
窄菲美珞: JAVA中线程安全的map有:Hashtable、synchronizedMap、ConcurrentHashMap.java中map中线程安全怎么实现:1. 同步的map就是Hashtable, concurrenthashmap.2. 你看到的Hashtable就是直接在hashmap上加了个锁,concurrenthashmap...
樟树市18613215211: 如何解决java中线程安全问题 - ?
窄菲美珞: java中,线程安全的解决方法或过程: 1.如果对象是immutable,则是线程安全的,例如:String,可以放心使用. 2. 如果对象是线程安全的,则放心使用. 3.有条件线程安全,对于Vector和Hashtable一般情况下是线程安全的,但是对于某些特殊情况,需要通过额外的synchronized保证线程安全. 4.使用synchronized关键字.
樟树市18613215211: java中为什么说,String是线程安全的? - ?
窄菲美珞: String是不可变类,所以是线程安全的. 1、所有不可变类都是线程安全的,线程安全的类不一定是不可变类,如StringBuffer是可变类,靠锁实现线程安全.2、StringBuffer方法上都加了synchronized,StringBuilder没有,StringBuilder在多线程...
樟树市18613215211: java 中为什么说,String是线程安全的 - ?
窄菲美珞: 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 或者说:一个类或者程序所提供的接口...
樟树市18613215211: java中map中线程安全怎么实现 - ?
窄菲美珞: hashtable、synchronizedmap、concurrenthashmap二楼说的hashmap是非线程安全的
樟树市18613215211: 在java中线程安全与同步的关系? - ?
窄菲美珞: 1、java中线程同步了也就满足安全性.2、web工程中每一个浏览器发出的http请求到达服务器的时候,服务器都会建立一个新的线程来处理请求,一般如果写的action中很少会有静态的变量.a.如果没有静态变量(静态变量都是所有action中唯...
樟树市18613215211: 怎么理解集合中线程安全和不安全的问题 - ?
窄菲美珞: 线程安全,就是集合里面的元素可以随便任意多个人同时读写,不会出问题;线程不安全就是不能多个人随便一起操作会乱套的.