欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java线程操作JUC相关笔记

程序员文章站 2022-04-17 21:37:06
...

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一个,用完了又要销毁,这样频繁的创建销毁也很耗资源,所以就提供了线程池。道理和连接池差不多,连接池是为了避免频繁的创建和释放连接,所以在连接池中就有一定数量的连接,要用时从连接池拿出,用完归还给连接池。线程池也一样。线程池中有一个线程队列,里面保存着所有等待状态的线程。下面来看一下用法。

相关标签: JUC