18.ReadWriteLock
读写锁
/**
* 独占锁(写锁)一次只能被一个线程占有
* 共享锁(读锁)多个线程可以同时占有
* ReadWriteLock
* 读-读 可以共存!
* 读-写 不能共存!
* 写-写 不能共存!
*
*/
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCacheLock myCache = new MyCacheLock();
for (int i = 1; i <= 5; i++) {
final String temp = String.valueOf(i);
new Thread(() -> {
myCache.put(temp, temp);
}, temp).start();
}
for (int i = 1; i <= 5; i++) {
final String temp = String.valueOf(i);
new Thread(() -> {
myCache.get(temp);
}, temp).start();
}
}
}
class MyCacheLock {
private volatile Map<String, Object> map = new HashMap<>();
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//存,写
public void put(String key, Object value) {
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "写入" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "写入ok");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
//取,读
public void get(String key) {
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "读取" + key);
map.get(key);
System.out.println(Thread.currentThread().getName() + "读取ok");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
class MyCache {
private volatile Map<String, Object> map = new HashMap<>();
//存,写
public void put(String key, Object value) {
System.out.println(Thread.currentThread().getName() + "写入" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "写入ok");
}
//取,读
public void get(String key) {
System.out.println(Thread.currentThread().getName() + "读取" + key);
map.get(key);
System.out.println(Thread.currentThread().getName() + "读取ok");
}
}
输出
1写入1
1写入ok
3写入3
3写入ok
4写入4
4写入ok
2写入2
2写入ok
2读取2
2读取ok
1读取1
1读取ok
5写入5
5写入ok
4读取4
4读取ok
5读取5
3读取3
5读取ok
3读取ok
19.阻塞队列BlockingQueue
阻塞队列
-
阻塞队列
-
非阻塞队列
-
双端队列
什么情况下我们会使用阻塞队列? – 多线程并发处理,线程池!
使用队列
- 添加
- 移除
20.BlockingQueue四组API
四组API
- 有返回值,抛出异常
- 有返回值,不抛出异常
- 阻塞等待
- 超时等待
方式 | 有返回值,抛出异常 | 有返回值,不抛出异常 | 阻塞等待 | 超时等待 |
---|---|---|---|---|
添加 | add() | offer() | put() | offer(,) |
移除 | remove() | poll() | take() | poll(,) |
查看队列首元素 | element() | peek() | - | - |
/**
* 有返回值,抛出异常
*/
public static void test1() {
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
//抛出异常 java.lang.IllegalStateException: Queue full
// System.out.println(blockingQueue.add("d"));
//查看队列首元素
System.out.println(blockingQueue.element());
System.out.println("===================");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//抛出异常 java.util.NoSuchElementException
// System.out.println(blockingQueue.remove());
}
/**
* 有返回值,不抛出异常
*/
public static void test2() {
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
//不抛出异常,返回false
System.out.println(blockingQueue.offer("d"));
//查看队列首元素
System.out.println(blockingQueue.peek());
System.out.println("===================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
//不抛出异常,返回null
System.out.println(blockingQueue.poll());
}
/**
* 阻塞等待,一直等
*/
public static void test3() {
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
try {
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
//队列没有位置了,一直阻塞
// blockingQueue.put("d");
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
//队列没有元素了,一直阻塞
// System.out.println(blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 超时等待
*/
public static void test4() {
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
try {
System.out.println(blockingQueue.offer("a", 2, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("b", 2, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("c", 2, TimeUnit.SECONDS));
//等待超过2秒 返回false
System.out.println(blockingQueue.offer("d", 2, TimeUnit.SECONDS));
System.out.println("================");
System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
//等待超过2秒 返回null
System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
21.同步队列SynchronousQueue
没有容量
进去一个元素,必须等待取出来之后,才能再往里面放一个元素!
put、take
public class SynchronousQueueDemo {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new SynchronousQueue<>();
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " put a");
blockingQueue.put("a");
System.out.println(Thread.currentThread().getName() + " put b");
blockingQueue.put("b");
System.out.println(Thread.currentThread().getName() + " put c");
blockingQueue.put("c");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1").start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + " ==> " + blockingQueue.take());
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + " ==> " + blockingQueue.take());
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + " ==> " + blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T2").start();
}
}
输出
T1 put a
T2 ==> a
T1 put b
T2 ==> b
T1 put c
T2 ==> c