这篇文章将为大家详细讲解有关java高并发同步容器指的是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
在java中同步容器主要包括两类:
ArrayList -> Vector,Stack; HashMap -> HashTable(key,value不能为null)
Collections.synchronizedXXX(List, Set, Map)
Vector实现了List接口,实际上就是一个数组。与ArrayList非常类似。但是Vector中的所有方法都是使用synchronized方法修饰的方法,进行了同步的措施。因此在多线程环境下使用ArrayList对象时,如果被多个线程共享使用可以换成同步的Vector,这样的话线程安全型会更好一些(而不是完全线程安全的)。
@Slf4j
@ThreadSafe
public class VectorExample1 {
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
private static List<Integer> list = new Vector<>();
public static void main(String[] args) throws InterruptedException {
//线程池
ExecutorService executorService = Executors.newCachedThreadPool();
//定义信号量
final Semaphore semaphore = new Semaphore(threadTotal);
//定义计数器
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for(int i = 0; i < clientTotal; i++) {
final int count = i;
executorService.execute(() ->{
try {
semaphore.acquire();
update(count);
semaphore.release();
} catch (InterruptedException e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("size:{}",list.size()) ;
}
public static void update(int i) {
list.add(i);
}
}
这样输出的结果就是预期的结果。
@NotThreadSafe
public class VectorExample2 {
private static Vector<Integer> vector = new Vector<>();
public static void main(String[] args) {
while (true){
for (int i = 0;i < 10;i++) {
vector.add(i);
}
Thread thread1 = new Thread(){
@Override
public void run() {
for (int i = 0;i < vector.size();i++) {
vector.remove(i);
}
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
for (int i = 0;i < vector.size();i++) {
vector.get(i);
}
}
};
thread1.start();
thread2.start();
}
}
}
运行,抛出异常:
Exception in thread "Thread-611" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 5
at java.util.Vector.get(Vector.java:748)
at com.vincent.example.syncContainer.VectorExample2$2.run(VectorExample2.java:25)
Exception in thread "Thread-1759" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 21
at java.util.Vector.get(Vector.java:748)
at com.vincent.example.syncContainer.VectorExample2$2.run(VectorExample2.java:25)
原因:get发生越界肯定是remove方法引起的,vector虽然能保证同一时刻只能有一个线程能访问他,但是不排除有这种可能:当某个线程某个时刻执行到int i = 0;i < vector.size()时,vector.size()返回10,i=9;而另外一个线程正好将i=9的vector移除掉了,这时get方法想调用i=9的元素就会出现数组越界的异常。
这个例子演示了两个同步容器的两个同步方法因为操作顺序的差异,在不同线程里面可能会触发线程不安全的问题。因此为了保证线程安全,必须在方法调用端做一些额外的同步措施才可以。在使用同步容器时并不是在所有场合下都是线程安全的。
Stack中的方法也使用了synchronized修饰了,实际上Stack类继承了Vector类。
HashTable实现了Map接口,与HashMap很相似,但是HashTable进行了同步处理,方法也是使用了synchronized进行了修饰。但是在使用HashTable时一定要注意key和value是不能为null的。
将新建ArrayList、HashSet、HashMap对象由Collections产生:
private static List<Integer> list = Collections.synchronizedList(new ArrayList<>());
private static Set<Integer> set = Collections.synchronizedSet(new HashSet<>());
private static Map<Integer, Integer> map = Collections.synchronizedMap(new HashMap<>());
public class VectorExample3 {
//Exception in thread "main" java.util.ConcurrentModificationException
private static void test1(Vector<Integer> v1){ //foreach
for(Integer i: v1){
if(i.equals(3)){
v1.remove(i);
}
}
}
//Exception in thread "main" java.util.ConcurrentModificationException
private static void test2(Vector<Integer> v1){ //iterator
Iterator<Integer> integerIterator = v1.iterator();
while (integerIterator.hasNext()) {
Integer i = integerIterator.next();
if(i.equals(3)){
v1.remove(i);
}
}
}
// success
private static void test3(Vector<Integer> v1){
for(int i = 0; i < v1.size(); i++) {
if(v1.equals(3)){
v1.remove(i);
}
}
}
public static void main(String[] args) {
Vector<Integer> vector = new Vector<>();
vector.add(1);
vector.add(2);
vector.add(3);
test1(vector);
}
}
如果使用了Foreach或者迭代器来循环我们的集合时,尽量不要在循环中做集合的删除操作,如果要做remove操作时,建议在遍历的过程中发现需要删除的值然后做一个标记,在遍历结束后在执行相应的remove操作。在多线程情况下出现异常的情况会更大。
关于java高并发同步容器指的是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/duanvincent/blog/3080632