首先给出结论,ArrayList,LinkedList,HashMap,StringBuilder是不安全的。vector,HashTable,StringBuffer是线程安全的。下面用代码来看看。
Java API中所用的集合类,都是实现了Collection接口,他的一个类继承结构如下: Collection<–List<–Vector Collection<–List<–ArrayList Collection<–List<–LinkedList Collection<–Set<–HashSet Collection<–Set<–HashSet<–LinkedHashSet Collection<–Set<–SortedSet<–TreeSet Vector : 基于Array的List,其实就是封装了Array所不具备的一些功能方便我们使用,它不可能走入Array的限制。性能也就不可能超越Array。所以,在可能的情况下,我们要多运用Array。另外很重要的一点就是Vector“sychronized”的,这个也是Vector和ArrayList的唯一的区别。 ArrayList:同Vector一样是一个基于Array上的链表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector优越一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。 LinkedList:LinkedList不同于前面两种List,它不是基于Array的,所以不受Array性能的限制。它每一个节点(Node)都包含两方面的内容:1.节点本身的数据(data);2.下一个节点的信息(nextNode)。所以当对LinkedList做添加,删除动作的时候就不用像基于Array的List一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了。这就是LinkedList的优势。 List总结: 1. 所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ]; 2. 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]; 3. 所有的List中可以有null元素,例如[ tom,null,1 ]; 4. 基于Array的List(Vector,ArrayList)适合查询,而LinkedList(链表)适合添加,删除操作。 HashSet:虽然Set同List都实现了Collection接口,但是他们的实现方式却大不一样。List基本上都是以Array为基础。但是Set则是在HashMap的基础上来实现的,这个就是Set和List的根本区别。HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。
- ArrayList测试
package testThread;
import java.util.ArrayList;
import java.util.List;
class Ticket implements Runnable {
private static int t=0;
List<Integer> data = new ArrayList<>();
boolean flag=true;
public void run() {
while (flag) {
if (t<100) {
data.add(t);
t++;
//System.out.println(t);
}else {
flag=false;
System.out.println("数据宽度"+data.size());
for (int i = 0; i < data.size(); i++) {
System.out.println(data.get(i));
}
}
}
}
}
public class thread1 {
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
ArrayList测试结果
2.LinkedList
package te;
import java.util.LinkedList;
import java.util.List;
class Ticket implements Runnable {
private static int t=0;
List<Integer> data = new LinkedList<Integer>();
boolean flag=true;
public void run() {
while (flag) {
if (t<100) {
data.add(t);
t++;
//System.out.println(t);
}else {
flag=false;
System.out.println("数据宽度"+data.size());
for (int i = 0; i < data.size(); i++) {
System.out.println(data.get(i));
}
}
}
}
}
public class Thread7 {
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
LinkedList结果
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/0bae3c9cefca23f62a308c76b026b8de.png)
3.HashMap
package te;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
class Ticket implements Runnable {
private static int t=0;
Map data = new HashMap<Integer,Integer>();
boolean flag=true;
public void run() {
while (flag) {
if (t<100) {
data.put(t,t);
t++;
//System.out.println(t);
}else {
flag=false;
Collection da=data.values();
Iterator<Integer> it=da.iterator();
while (it.hasNext()) {
Integer integer = (Integer) it.next();
System.err.println(integer);
}
}
}
}
}
public class Thread7 {
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
HashMap测试
4.vector
package te;
import java.util.Vector;
class Ticket implements Runnable {
private static int t=0;
Vector<Integer> vector=new Vector<Integer>();
boolean flag=true;
public void run() {
while (flag) {
if (t<100) {
vector.add(t);
t++;
}else {
flag=false;
for(int i=0;i<vector.size();i++)
{
System.out.println(vector.get(i));
}
}
}
}
}
public class Thread7 {
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
vector线程是安全的
5.stringbuilder和stringbuffer
package te;
class Ticket implements Runnable {
private static int t=0;
StringBuffer sb = new StringBuffer();
StringBuilder sc=new StringBuilder();
boolean flag=true;
public void run() {
while (flag) {
if (t<100) {
sb.append(t+"a ");
sc.append(t+"a ");
t++;
}else {
flag=false;
System.out.println("stringbuffer"+sb);
System.out.println("stringbuilder"+sc);
}
}
}
}
public class Thread7 {
public static void main(String[] args)
{
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
结果测试 stringbuilder是不安全的
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/d1377fbd0a438c2cd1b5eaa633859e3f.png)
6.分析总结
凡是线程不安全的,我们可以来看源码来分析 ,这是arraylist的源码,我们很容易发现这是由于没有synchronized关键字。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
再来看看vector,有synchronized关键字。
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}