Java线程操作JUC相关笔记
JUC
volatile 关键字
- volatile 关键字: 当多个线程进行操作共享数据时,可以保证内存中的数据是可见的;相较于 synchronized是一种
较为轻量级的同步策略; - volatile 不具备"互斥性";
- volatile 不能保证变量的"原子性";
CAS算法
- CAS(Compare-And-Swap) 算法是硬件对于并发的支持,针对多处理器操作而设计的处理器中的一种特殊指令,用于管理对共享数据的并发访问;
- CAS 是一种无锁的非阻塞算法的实现;
-
- 需要读写的内存值: V
- 进行比较的预估值: A
- 拟写入的更新值: B
- 当且仅当 V == A 时, V = B, 否则,将不做任何操作;
并发容器类
Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能;
ConcurrentHashMap
1、ConcurrentHashMap:ConcurrentHashMap就是一个线程安全的hash表。我们知道HashMap是线程不安全的,Hash Table加了锁,是线程安全的,因此它效率低。HashTable加锁就是将整个hash表锁起来,当有多个线程访问时,同一时间只能有一个线程访问,并行变成串行,因此效率低。
CountDownLatch(闭锁)
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待;
// 一个简单的例子:利用CountDownLatch辅助类计算所有是个子线程的执行时间
public class TestCountDownLatch {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(10);//有多少个线程这个参数就是几
LatchDemo ld = new LatchDemo(latch);
long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
new Thread(ld).start();
}
try {
latch.await();//这10个线程执行完之前先等待
} catch (InterruptedException e) {
}
long end = System.currentTimeMillis();
System.out.println("耗费时间为:" + (end - start));
}
}
class LatchDemo implements Runnable {
private CountDownLatch latch;
public LatchDemo(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
synchronized (this) {
try {
for (int i = 0; i < 50000; i++) {
if (i % 2 == 0) {//50000以内的偶数
System.out.println(i);
}
}
} finally {
latch.countDown();//每执行完一个就递减一个
}
}
}
}
创建线程的方式 (Callable Runnable)
相较于实现 Runnable 接口的方式,实现 Callable 接口类中的方法可以有返回值,并且可以抛出异常;
现在Callable接口和实现Runnable接口的区别就是,Callable带泛型,其call方法有返回值。使用的时候,需要用FutureTask来接收返回值。而且它也要等到线程执行完调用get方法才会执行,也可以用于闭锁操作。
Lock同步锁
Lock需要通过lock()方法上锁,通过unlock()方法释放锁。为了保证锁能释放,所有unlock方法一般放在finally中去执行。
代码参见: LockUserForCondition.java类
ReadWriteLock(读写锁)
我们在读数据的时候,可以多个线程同时读,不会出现问题,但是写数据的时候,如果多个线程同时写数据,那么到底是写入哪个线程的数据呢?所以,如果有两个线程,写写/读写需要互斥,读读不需要互斥。这个时候可以用读写锁
https://www.jianshu.com/p/1f19835e05c0
https://www.cnblogs.com/linkworld/p/7819270.html
线程池
使用线程时,需要new一个,用完了又要销毁,这样频繁的创建销毁也很耗资源,所以就提供了线程池。道理和连接池差不多,连接池是为了避免频繁的创建和释放连接,所以在连接池中就有一定数量的连接,要用时从连接池拿出,用完归还给连接池。线程池也一样。线程池中有一个线程队列,里面保存着所有等待状态的线程。下面来看一下用法。
上一篇: 盲和亡的对话