原子类
AtomicLong 、 AtomicInteger …等
用于防止多线程下类似于数据库脏读的发生。
如果一个操作分为两步执行,第一步读取当前的状态,第二步,如果状态符合要求。
就更新,否者不更新。 那么就可以使用上面的原子类实现
package com.zf.colcurrent;
import java.util.concurrent.atomic.AtomicLong;
publicclass CasTest {
publicstaticvoid main(String[] args) {
AtomicLong al = new AtomicLong();
al.set(1000); //将值设为 1000
al.compareAndSet(500, 80); //更新失败,因为预期的值为500与实际不符合
System.out.println(al);
al.compareAndSet(1000, 80);//更新成功,预期的值与原始的值符合。将值更新为80
System.out.println(al);
}
}
PriorityQueue 优先级队列(存放的对象需要实现Comparator接口)
package com.zf.colcurrent;
import java.util.PriorityQueue;
import java.util.Queue;
publicclass PriorityQueueTest {
publicstaticvoid main(String[] args) {
Queue<Integer> queue = new PriorityQueue<Integer>();
queue.add(5);
queue.add(3);
queue.add(6);
queue.add(2);
while(!queue.isEmpty())
System.out.println(queue.poll());
}
}
BlockingQueue 阻塞队列
实例化该对象时候,需要在构造方法上面给一个容量。
放入对象的时候,判断队列是否已满,如果满了,就阻塞,直到队列非满, 取出对象的时候判断队列是否为空,如果为空,就阻塞,知道队列非空。 方法分别为 put() 、 tack()
典型的可用于生产者与消费者问题中。
该接口的实现类常用的有:ArrayBlockingQueue、 LinkedBlockingQueue、PriorityBlockingQueue(优先级阻塞队列)
线程安全map,继承自Map。
ConcurrentHashMap
public class ConCurrentMapTest {
public static void main(String[] args) {
final ConcurrentMap<String, String> map =newConcurrentHashMap<String, String>();
/*
如果key不存在,就将该键值对添加到map并返回newValue,如果已经存在key,就直接返回已存在的value
并且整个过程是原子的(也就是线程安全的)
*/
map.putIfAbsent("key", "newValue") ;
/*
如果map中存在指定的key,并且对应的值也等于 oldValue。那么就移除。否则不做任何操作
并且整个过程也是原子的
*/
map.remove("key" , "oldValue") ;
/*
如果map中存在指定的key并且对应的值为 oldValue,那么就将值替换为newValue
否则不做任何草组。整个过程是原子的。
*/
map.replace("key", "oldValue", "newValue");
}
}
防止ConcurrentModificationException异常的集合类
CopyOnWriteArrayList
普通List在使用Iterator迭代器遍历集合的同时,如果集合被修改了。就会抛出并发异常。
CopyOnWriteArrayList 在使用Iterator遍历时,是复制了原数组的一个副本,用来遍历。即使原数组同时被修改了。也不会发生异常。 该集合类适用于频繁读取。修改少的集合
public class CopyOnWriteArrayListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
List<String> cowal = new CopyOnWriteArrayList<String>() ;
list.add("old");
cowal.add("old");
Iterator<String> it1 = list.iterator();
Iterator<String> it2 = cowal.iterator();
//向集合中添加信元素
list.add("new");
cowal.add("new");
while(it1.hasNext()){//这里将会抛ConcurrentModificationException异常,因为原集合被修改了
try{
System.out.println(it1.next());
}catch(ConcurrentModificationException e){
System.out.println("发生并发修改异常!");
break ;
}
}
while(it2.hasNext()){//这里会正常运行。
System.out.println(it2.next());
}
}
}
信号量Semaphore用来限制资源最多能够被多少个线程同时访问。
package com.zf.thread;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* 下面的例子 是用Semaphore对象对SemaphoreDemo的m1方法限制为同时只能有3个线程访问m1方法
* @author Administrator
*
*/
public class SemaphoreDemo {
//信号量
final Semaphoresemaphore =new Semaphore(3,true);
/* 用Semaphore来控制同一时刻,只能有3条线程同时访问该方法 */
public void m1() throws InterruptedException{
semaphore.acquire(); //获得许可
System.out.println(Thread.currentThread().getName() +"正在访问m1..." );
TimeUnit.SECONDS.sleep(3); //睡眠3s
semaphore.release(); //访问完毕,释放许可
}
public static void main(String[] args) {
final SemaphoreDemo sd =new SemaphoreDemo();
Runnable rannable = new Runnable() {
public void run() {
try {
sd.m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//用10条线程访问
for (int i = 0; i < 10 ; i++) {
new Thread(rannable).start();
}
}
}