Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列

JUC是什么?

JUC是java.util.concurrent包的简称,在Java5.0添加,目的就是为了更好的支持高并发任务。让开发者进行多线程编程时减少竞争条件和死锁的问题


Java中线程有六个状态

java.lang.Thread.State

public enum State {
       // 新生
        NEW,

        // 运行
        RUNNABLE,

        // 阻塞
        BLOCKED,

        // 等待
        WAITING,

        //超时等待
        TIMED_WAITING,

        //终止
        TERMINATED;
    }


JUC的结构 

tools(工具类):又叫信号量三组工具类,包含有

CountDownLatch(闭锁) 是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待

CyclicBarrier(栅栏) 之所以叫barrier,是因为是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ,并且在释放等待线程后可以重用。

Semaphore(信号量) 是一个计数信号量,它的本质是一个“共享锁“。信号量维护了一个信号量许可集。线程可以通过调用 acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

executor(执行者):是Java里面线程池的顶级接口,但它只是一个执行线程的工具,真正的线程池接口是ExecutorService,里面包含的类有:

ScheduledExecutorService 解决那些需要任务重复执行的问题

ScheduledThreadPoolExecutor 周期性任务调度的类实现

atomic(原子性包):是JDK提供的一组原子操作类

包含有AtomicBoolean、AtomicInteger、AtomicIntegerArray等原子变量类,他们的实现原理大多是持有它们各自的对应的类型变量value,而且被volatile关键字修饰了。这样来保证每次一个线程要使用它都会拿到最新的值。

locks(锁包):是JDK提供的锁机制,相比synchronized关键字来进行同步锁,功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁包含的实现类有:

ReentrantLock 它是独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。

ReentrantReadWriteLock 它包括子类ReadLock和WriteLock。ReadLock是共享锁,而WriteLock是独占锁。

LockSupport 它具备阻塞线程和解除阻塞线程的功能,并且不会引发死锁。

collections(集合类):主要是提供线程安全的集合, 比如:

ArrayList对应的高并发类是CopyOnWriteArrayList,

HashSet对应的高并发类是 CopyOnWriteArraySet,

HashMap对应的高并发类是ConcurrentHashMap等等


synchronized和JUC的Lock

synchronized和lock锁的区别

synchronized内置的java关键字,Lock是一个java类
synchronized无法判断获取锁的状态, Lock可以判断是否获取到了锁
synchronized会自动释放锁,Lock必须要手动释放锁!如果不是释放锁,会产生死锁
synchronized 线程1(获得锁,阻塞),线程2(等待); Lock锁就不一定会等待下去
synchronized 可重入锁,不可以中断的,非公平的; Lock锁,可重入的,可以判断锁,非公平(可自己设置);
synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的同步代码


reentrantLock

ReentrantLock 和 synchronized 的区别:

🍃1.synchronized 使用时不需要手动释放锁. ReentrantLock 使用时需要手动释放. 使用起来更灵活, 但是也容易遗漏 unlock。

🍃2.synchronized只是非公平锁,ReentranLock 提供了公平锁和非公平锁两种实现,可以通过构造方法来切换。

🍃3.ReentrantLock 还提供了一个特殊的加锁操作-- tryLock()。默认的 lock() 加锁失败就阻塞,而 tryLock() 加锁失败,则不阻塞,继续往下执行,并且返回 false。除了立即失败之外,tryLock() 还能设定一定的等待时间。

🍃4.ReentrantLock 提供了更强大的等待/唤醒 机制。 synchronized 搭配的是 Object 类的 wait,notify,只能随机唤醒其中一个线程;ReentrantLock 搭配了 Condition 类来实现等待唤醒,可以做到能随机唤醒一个,也能指定线程唤醒。

构造方法:

  	public ReentrantLock() {
        sync = new NonfairSync(); //无参默认非公平锁
    }
 	public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();//传参为true为公平锁
    }
 
public class SaleTicketDemo {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();

        new Thread(()->{for(int i = 0; i < 40; i++) ticket.sale();}, "a").start();
        new Thread(()->{for(int i = 0; i < 40; i++) ticket.sale();}, "b").start();
        new Thread(()->{for(int i = 0; i < 40; i++) ticket.sale();}, "c").start();

    }
}

class Ticket {

    private int ticketNum = 30;
    private Lock lock = new ReentrantLock();

    public void sale() {
        lock.lock();
        try {
            if (this.ticketNum > 0) {
                System.out.println(Thread.currentThread().getName() + "购得第" + ticketNum-- + "张票, 剩余" + ticketNum + "张票");
            }
            //增加错误的发生几率
            Thread.sleep(10);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}


Condition

精准的通知和唤醒线程
Condition是个接口,基本的方法就是await()和signal()方法;
Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
Conditon中的await()对应Object的wait();

Condition中的signal()对应Object的notify();

Condition中的signalAll()对应Object的notifyAll()。

对比项 Object Monitor Methods
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值