Lock接口
JDK1.5后,又加入一套实现同步的API:Lock接口
与synchronized比较,Lock显示定义,结构更灵活,提供更多实用性方法,功能更强大、性能更优越。
常用方法:
void lock // 获取锁,如锁被占用,则等待
boolean tryLock() //尝试获取锁(成功返回true,失败返回false,不阻塞)
void unlock() // 释放锁
重入锁 Reentrantlock
为什么把.unlock()放到finally里?
不管try中代码是否发生异常,finally中代码都会执行,为了保证一定能解锁。
读写锁 ReentrantReadWriteLock
- 一种支持一写多度的同步锁,读写分离,可分别分配读锁、写锁
- 支持对此分配读锁,使多个读操作可以并发执行。
互斥规则:
写写:互斥,阻塞
读写:互斥,读阻塞写,写阻塞读
读读:不互斥,不阻塞
线程安全的集合
package Lock_01;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class XianChengAnQuanYanShi {
//演示:使用多线程操作线程不安全集合
public static void main(String[] args) {
//1.创建一个线程不安全的集合
//ArrayList<String> arraylist = new ArrayList<>();
// 怎么将这个集合变成线程安全的集合?
//方法1.1使用Collections中的线程安全方法转成线程安全的集合
//List<String> synlist = Collections.synchronizedList(arraylist); // 下面的arraylist记得改成synlist
//方法1.2使用CopyOnWriteArrayList
CopyOnWriteArrayList<String> arraylist = new CopyOnWriteArrayList<>();
//2.创建线程
for(int i=0;i<20;i++) {
int temp=i;
new Thread(new Runnable() {
@Override
public void run() {
//每个线程都向集合中添加10个元素
// TODO Auto-generated method stub
for(int j=0;j<10;j++) {
arraylist.add(Thread.currentThread().getName()+"==="+temp+"==="+j);
//打印集合元素
System.out.println(arraylist.toString());
}
}
}).start();
}
}
}
CopyOnWriteArrayList
缺点是浪费时间
package Lock_01;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CopyOnWrite {
public static void main(String[] args) {
//1创建集合
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
//2使用多线程操作
ExecutorService es = Executors.newFixedThreadPool(5);
//3提交任务
for(int i=0;i<5;i++) {
es.submit(new Runnable() { //匿名内部类
@Override
public void run() {
// TODO Auto-generated method stub
// 每个线程都向集合中添加10个元素
for(int j=0;j<10;j++){
list.add(Thread.currentThread().getName()+"..."+new Random().nextInt(1000));
}
}
});
}
//4关闭线程池
es.shutdown();
while(!es.isTerminated()) { //空转
}
//5打印结果
System.out.println("元素个数"+list.size());
for(String string:list) {//增强for循环
System.out.println(string);
}
}
}
CopyOnWriteArraySet
Queue接口
ConcurrentLinkedQueue(非阻塞队列/无界队列)
BlockingQueue接口(阻塞队列/有界队列)