同步容器

博客介绍了Java中的同步容器类,包括JDK早期的Vector和HashTable,以及由Collections.synchronizedXXX创建的封装容器类。阐述了Vector可增长对象数组的特性、Stack后进先出的特点和HashTable通过散列函数加快查找速度的原理,还提及了它们的线程安全问题。

同步容器类包括Vector和HashTable,这两个都是JDK早期的容器。后来在JDK1.2也引入一个功能与之类似的类,这些同步的封装容器类是由Collections.synchronizedXXX等工厂方法创建的。这些类实现线程安全的方式是:将他们的状态封装起来,并对每个公有方法都进行同步,使得每次只有线程能访问容器的状态。

Vector:

Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。 

构造函数:

Vector()
          构造一个空向量,使其内部数据数组的大小为 10,其标准容量增量为零。
Vector(Collection<? extends E> c)
          构造一个包含指定 collection 中的元素的向量,这些元素按其 collection 的迭代器返回元素的顺序排列。
Vector(int initialCapacity)
          使用指定的初始容量和等于零的容量增量构造一个空向量。
Vector(int initialCapacity, int capacityIncrement)
          使用指定的初始容量和容量增量构造一个空的向量。

主要方法:

 booleanadd(E e)
          将指定元素添加到此向量的末尾。
 voidadd(int index, E element)
          在此向量的指定位置插入指定的元素。
 booleanaddAll(Collection<? extends E> c)
          将指定 Collection 中的所有元素添加到此向量的末尾,按照指定 collection 的迭代器所返回的顺序添加这些元素。
 booleanaddAll(int index, Collection<? extends E> c)
          在指定位置将指定 Collection 中的所有元素插入到此向量中。
 voidaddElement(E obj)
          将指定的组件添加到此向量的末尾,将其大小增加 1。
 intcapacity()
          返回此向量的当前容量。
 voidclear()
          从此向量中移除所有元素。
 Objectclone()
          返回向量的一个副本。
 booleancontains(Object o)
          如果此向量包含指定的元素,则返回 true
 booleancontainsAll(Collection<?> c)
          如果此向量包含指定 Collection 中的所有元素,则返回 true。
 voidcopyInto(Object[] anArray)
          将此向量的组件复制到指定的数组中。
 EelementAt(int index)
          返回指定索引处的组件。
 Enumeration<E>elements()
          返回此向量的组件的枚举。
 voidensureCapacity(int minCapacity)
          增加此向量的容量(如有必要),以确保其至少能够保存最小容量参数指定的组件数。
 booleanequals(Object o)
          比较指定对象与此向量的相等性。
 EfirstElement()
          返回此向量的第一个组件(位于索引 0) 处的项)。
 Eget(int index)
          返回向量中指定位置的元素。
 inthashCode()
          返回此向量的哈希码值。
 intindexOf(Object o)
          返回此向量中第一次出现的指定元素的索引,如果此向量不包含该元素,则返回 -1。
 intindexOf(Object o, int index)
          返回此向量中第一次出现的指定元素的索引,从 index 处正向搜索,如果未找到该元素,则返回 -1。
 voidinsertElementAt(E obj, int index)
          将指定对象作为此向量中的组件插入到指定的 index 处。
 booleanisEmpty()
          测试此向量是否不包含组件。
 ElastElement()
          返回此向量的最后一个组件。
 intlastIndexOf(Object o)
          返回此向量中最后一次出现的指定元素的索引;如果此向量不包含该元素,则返回 -1。
 intlastIndexOf(Object o, int index)
          返回此向量中最后一次出现的指定元素的索引,从 index 处逆向搜索,如果未找到该元素,则返回 -1。
 Eremove(int index)
          移除此向量中指定位置的元素。
 booleanremove(Object o)
          移除此向量中指定元素的第一个匹配项,如果向量不包含该元素,则元素保持不变。
 booleanremoveAll(Collection<?> c)
          从此向量中移除包含在指定 Collection 中的所有元素。
 voidremoveAllElements()
          从此向量中移除全部组件,并将其大小设置为零。
 booleanremoveElement(Object obj)
          从此向量中移除变量的第一个(索引最小的)匹配项。
 voidremoveElementAt(int index)
          删除指定索引处的组件。
protected  voidremoveRange(int fromIndex, int toIndex)
          从此 List 中移除其索引位于 fromIndex(包括)与 toIndex(不包括)之间的所有元素。
 booleanretainAll(Collection<?> c)
          在此向量中仅保留包含在指定 Collection 中的元素。
 Eset(int index, E element)
          用指定的元素替换此向量中指定位置处的元素。
 voidsetElementAt(E obj, int index)
          将此向量指定 index 处的组件设置为指定的对象。
 voidsetSize(int newSize)
          设置此向量的大小。
 intsize()
          返回此向量中的组件数。
 List<E>subList(int fromIndex, int toIndex)
          返回此 List 的部分视图,元素范围为从 fromIndex(包括)到 toIndex(不包括)。
 Object[]toArray()
          返回一个数组,包含此向量中以恰当顺序存放的所有元素。
<T> T[]
toArray(T[] a)
          返回一个数组,包含此向量中以恰当顺序存放的所有元素;返回数组的运行时类型为指定数组的类型。
 StringtoString()
          返回此向量的字符串表示形式,其中包含每个元素的 String 表示形式。
 voidtrimToSize()
          对此向量的容量进行微调,使其等于向量的当前大小。

如果是单个方法进行调用是线程安全的,但是如果是组合的方式进行调用则需要再次进行同步处理

Vector 和 ArrayList 实现了同一接口 List, 但所有的 Vector 的方法都具有 synchronized 关键修饰。但对于复合操作,Vector 仍然需要进行同步处理

public static void main(String[] args) {
Vector<String> vector=new Vector();
for (int i = 0; i <12 ; i++) {
vector.add("第"+i+"名");

}
vector.remove(10);
for (String str:vector) {
System.out.println(str);
}
System.out.println(vector.size());
}


Stack

定义  栈是一种只能在一端进行插入或删除操作的线性表。(先进后出表)

Stack 类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 pushpop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的 search 方法。 

构造方法摘要:

Stack()
          创建一个空堆栈。

方法摘要:

 booleanempty()
          测试堆栈是否为空。
 Epeek()
          查看堆栈顶部的对象,但不从堆栈中移除它。
 Epop()
          移除堆栈顶部的对象,并作为此函数的值返回该对象。
 Epush(E item)
          把项压入堆栈顶部。
 intsearch(Object o)
          返回对象在堆栈中的位置,以 1 为基数。
public static void main(String[] args) {
Stack<Integer> stack=new Stack<>();
int index=0;
for (int i = 0; i < 10; i++) {
stack.add(index++);
}
if(!stack.isEmpty()){
System.out.println("我不为空");
}
System.out.println(stack.peek());
System.out.println(stack.pop());
System.out.println(stack.push(20));
System.out.println(stack.search(3));
}


HashTable

哈希表(HashTable)又叫做散列表,是根据关键码值(即键值对)而直接访问的数据结构。也就是说,它通过把关键码映射到表中一个位置来访问记录,以加快查找速度。看到这里你可能比较疑惑,它是怎么加快查找速度的?下一节就有说明!这个映射函数就叫做散列(哈希)函数,存放记录的数组叫做散列表。

此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。

为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。

Hashtable 的实例有两个参数影响其性能:初始容量加载因子容量 是哈希表中 的数量,初始容量 就是哈希表创建时的容量。

Collections.synchronized方法生成

构造方法摘要:

Hashtable()
          用默认的初始容量 (11) 和加载因子 (0.75) 构造一个新的空哈希表。
Hashtable(int initialCapacity)
          用指定初始容量和默认的加载因子 (0.75) 构造一个新的空哈希表。
Hashtable(int initialCapacity, float loadFactor)
          用指定初始容量和指定加载因子构造一个新的空哈希表。
Hashtable(Map<? extends K,? extends V> t)
          构造一个与给定的 Map 具有相同映射关系的新哈希表。

方法摘要:

 voidclear()
          将此哈希表清空,使其不包含任何键。
 Objectclone()
          创建此哈希表的浅表副本。
 booleancontains(Object value)
          测试此映射表中是否存在与指定值关联的键。
 booleancontainsKey(Object key)
          测试指定对象是否为此哈希表中的键。
 booleancontainsValue(Object value)
          如果此 Hashtable 将一个或多个键映射到此值,则返回 true。
 Enumeration<V>elements()
          返回此哈希表中的值的枚举。
 Set<Map.Entry<K,V>>entrySet()
          返回此映射中包含的键的 Set 视图。
 booleanequals(Object o)
          按照 Map 接口的定义,比较指定 Object 与此 Map 是否相等。
 Vget(Object key)
          返回指定键所映射到的值,如果此映射不包含此键的映射,则返回 null. 更确切地讲,如果此映射包含满足 (key.equals(k)) 的从键 k 到值 v 的映射,则此方法返回 v;否则,返回 null
 inthashCode()
          按照 Map 接口的定义,返回此 Map 的哈希码值。
 booleanisEmpty()
          测试此哈希表是否没有键映射到值。
 Enumeration<K>keys()
          返回此哈希表中的键的枚举。
 Set<K>keySet()
          返回此映射中包含的键的 Set 视图。
 Vput(K key, V value)
          将指定 key 映射到此哈希表中的指定 value
 voidputAll(Map<? extends K,? extends V> t)
          将指定映射的所有映射关系复制到此哈希表中,这些映射关系将替换此哈希表拥有的、针对当前指定映射中所有键的所有映射关系。
protected  voidrehash()
          增加此哈希表的容量并在内部对其进行重组,以便更有效地容纳和访问其元素。
 Vremove(Object key)
          从哈希表中移除该键及其相应的值。
 intsize()
          返回此哈希表中的键的数量。
 StringtoString()
          返回此 Hashtable 对象的字符串表示形式,其形式为 ASCII 字符 "" (逗号加空格)分隔开的、括在括号中的一组条目。
 Collection<V>values()
          返回此映射中包含的键的 Collection 视图。
   private static final int  maxTHread=5000;//总线程数量
private static final int concurrenceTHread=200;//并发线程数
private static Map<Integer,Integer> map=new Hashtable();

public static void main(String[] args) throws InterruptedException {
ExecutorService executorService=Executors.newCachedThreadPool();
final Semaphore semaphore=new Semaphore(concurrenceTHread);
final CountDownLatch countDownLatch=new CountDownLatch(maxTHread);
for (int i = 0; i < maxTHread; i++) {
final int count=i;
executorService.execute(()->{
try {
semaphore.acquire();//获取许可
update(count);
semaphore.release();//释放许可
} catch (Exception e) {
logger.info("result:"+e);
}
countDownLatch.countDown();//递减线程数量
});
}
countDownLatch.await();//等待
executorService.shutdown();//关闭线程池
logger.info("数量:"+map.size());


}
private static synchronized Integer update(int index){
return map.put(index,index);
}

Coollections工具类:
static
<T> Collection<T>
synchronizedCollection(Collection<T> c)
          返回指定 collection 支持的同步(线程安全的)collection。
static
<T> List<T>
synchronizedList(List<T> list)
          返回指定列表支持的同步(线程安全的)列表。
static
<K,V> Map<K,V>
synchronizedMap(Map<K,V> m)
          返回由指定映射支持的同步(线程安全的)映射。
static
<T> Set<T>
synchronizedSet(Set<T> s)
          返回指定 set 支持的同步(线程安全的)set。
static
<K,V> SortedMap<K,V>
synchronizedSortedMap(SortedMap<K,V> m)
          返回指定有序映射支持的同步(线程安全的)有序映射。
static
<T> SortedSet<T>
synchronizedSortedSet(SortedSet<T> s)
          返回指定有序 set 支持的同步(线程安全的)有序 set。
collections中不可变对象:
static
<T> Collection<T>
unmodifiableCollection(Collection<? extends T> c)
          返回指定 collection 的不可修改视图。
static
<T> List<T>
unmodifiableList(List<? extends T> list)
          返回指定列表的不可修改视图。
static
<K,V> Map<K,V>
unmodifiableMap(Map<? extends K,? extends V> m)
          返回指定映射的不可修改视图。
static
<T> Set<T>
unmodifiableSet(Set<? extends T> s)
          返回指定 set 的不可修改视图。
static
<K,V> SortedMap<K,V>
unmodifiableSortedMap(SortedMap<K,? extends V> m)
          返回指定有序映射的不可修改视图。
static
<T> SortedSet<T>
unmodifiableSortedSet(SortedSet<T> s)
          返回指定有序 set 的不可修改视图。
 
import com.google.common.collect.Lists; //Guava是一种基于开源的Java库,Google Guava源于2007年的"Google Collections Library"。

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>


private  static org.slf4j.Logger logger=LoggerFactory.getLogger(AtomicBoolExecutorService.class);
private static final int maxTHread=5000;//总线程数量
private static final int concurrenceTHread=200;//并发线程数
private static List<Integer> map=Collections.synchronizedList(Lists.newArrayList());

public static void main(String[] args) throws InterruptedException {
ExecutorService executorService=Executors.newCachedThreadPool();
final Semaphore semaphore=new Semaphore(concurrenceTHread);
final CountDownLatch countDownLatch=new CountDownLatch(maxTHread);
for (int i = 0; i < maxTHread; i++) {
final int count=i;
executorService.execute(()->{
try {
semaphore.acquire();//获取许可
update(count);
semaphore.release();//释放许可
} catch (Exception e) {
logger.info("result:"+e);
}
countDownLatch.countDown();//递减线程数量
});
}
countDownLatch.await();//等待
executorService.shutdown();//关闭线程池
logger.info("数量:"+map.size());
}
private static void update(int index){
map.add(index);
}
  • Collections.synchronized方法生成
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知青先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值