优秀的编程知识分享平台

网站首页 > 技术文章 正文

Vector, HashTable是线程同步的吗

nanyue 2024-08-12 22:28:36 技术文章 4 ℃

程序猿们大多都知道,Vector是ArrayList的多线程版本,HashTable是HashMap的多线程版本,Vector和HashTable都是线程安全的。对吧?

下面,我来写一个Vector的例子,验证下多线程的问题。

public class VectorTest {

public static void main(String[] args) {

final List<String> apples = new Vector<String>();

for(int i=0; i<10000; i++){

apples.add("apple"+i);

}

//add apples

Thread addThread = new Thread(){

@Override

public void run(){

while(true){

apples.add("apple"+new Random().nextInt());

}

}

};

Thread eatThread = new Thread(){

@Override

public void run(){

for(String apple : apples){

apples.remove(apple);

}

}

};

addThread.start();

eatThread.start();

}

}

这段代码,到底能否正常运行呢?Vector是线程安全的,现在2个线程,1个add操作,1个remove操作,应该没问题的吧。

图1 抛出异常

但事实是,抛出ConcurrentModificationException。Vector不是线程安全的吗?怎么现在2个线程同时访问Vector,怎么就出错了呢?

其实,是你搞错概念了。Vector是线程安全,但现在抛出的是同步修改异常。所有的集合类都有1个Fail-Fast的校验机制,当一个集合在被多个线程修改并访问时,就可能出现异常--ConcurrentModificationException。线程同步是为了保护集合中的数据不被脏读、写而设置的。

下面,让我们来写1个线程安全的正确例子:

public class VectorTest2 {

public static void main(String[] args) {

final List<String> apples = new Vector<String>();

for(int i=0; i<100; i++){

apples.add("apple"+i);

}

System.out.println("apples' size = "+apples.size());

for(int i = 0; i < 10; i++){

Thread eatThread = new Thread(){

@Override

public void run(){

while(apples.size() > 0){

System.out.println(Thread.currentThread().getId()+" eat Apple "+apples.remove(0));

}

}

};

eatThread.start();

}

}

}

现在,我们先初始化100个苹果,然后让10个人开始吃,10个吃完程序就结束了。

注意:我们说Vector, HashTable是线程安全的,指的是多个线程同时操作1个方法时,是安全的。而不是操作多个方法,操作多个方法那叫线程同步了。Vector, HashTable是线程安全的,但线程同步是需要自己去实现的。

最近发表
标签列表