什么是JUC

其实就是java.util.concurrent包的简称,最开始出现在JDK1.5中.

线程和进程

进程

一个运行中的程序集合,一个进程往往包含多个线程,至少包含1个线程,

Java中默认有2个线程,一个Mian线程,一个GC线程

线程

线程是操作系统弄够运算调度的最小单位,

对Java而言创建thread: 继承自thread,实现runnable接口,实现callable接口

Java真的可以开启线程吗? 开不了的,底层是用native关键词修饰.调用本地实现

并发和并行

并发(多线程操作同一个资源,交替执行)

  • CPU一核, 模拟出来多条线程,天下武功,唯快不破,快速交替

并行(多个人一起行走, 同时进行)

  • CPU多核,多个线程同时进行 ; 使用线程池操作

并发编程的本质:充分利用CPU的资源

Wait/Sleep的区别

  1. 来自不同的类

    wait来自object类, sleep来自线程类

  2. 关于锁的释放

    wait会释放锁, sleep不会释放锁

  3. 使用的范围不同

    wait必须在同步代码块中

    sleep可以在任何地方睡

  4. 是否需要捕获异常

    wait不需要捕获异常

    sleep需要捕获异常

Lock锁

Lock是一个接口,其基本功能和Synchronized 大差不差,两者对比如下:

Synchronized Lock
Java内置关键字 Java的一个接口
无法判断获取锁的状态 可以判断是否获取到锁
自动释放锁 必须手动释放
线程 1(获得锁,阻塞)、线程2(等待,傻傻的等) Lock锁就不一定会等待下去
可重入锁,不可以中断,非公平 可重入锁,可以判断锁,非公平(可设置)
适合少量代码 适合大量代码

Lock有三个实现类:

  • ReentrantLock 可重入锁(常用)
  • ReadLock 读锁
  • WriteLock 写锁

公平锁/非公平锁

公平锁: 十分公平: 可以先来后到,一定要排队

非公平锁: 十分不公平,可以插队(默认)

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();
}

static class Ticket {
    private int ticketNum = 30;
    private Lock lock = new ReentrantLock(true);
    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();
        }
    }
}

参考

文章1: https://blog.csdn.net/qq_22155255/article/details/109749311