一点点JUC的小姿势

发布时间 2023-10-04 16:59:58作者: 沈自在。

1 JUC

JUC就是java.util.concurrent下面的类包,专门用于多线程的开发。

1.1 并发与并行

  1. 并发

多线程操作同一个资源。

  • CPU 只有一核,模拟出来多条线程,天下武功,唯快不破。那么我们就可以使用CPU快速交替,来模拟多线程。
  • 并发编程的本质:充分利用CPU的资源!
  1. 并行

并行: 多个人一起行走

  • CPU多核,多个线程可以同时执行。 我们可以使用线程池!

1.2 线程的状态

public enum State {	
	//新生
    NEW,

	//运行
    RUNNABLE,

	//阻塞
    BLOCKED,

	//等待
    WAITING,

	//超时等待
    TIMED_WAITING,

	//终止
    TERMINATED;
}

1.3 wait/sleep

1、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

2.最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

 synchronized(x){ 
      x.notify() 
     //或者wait() 
   }

2 Lock锁

2.1 传统的 synchronized

public synchronized void sale(){
    if (sum > 0)
        System.out.println(Thread.currentThread().getName() + "获得了第:"+ sum + "张票,此时还剩 " + --sum);
}

2.2 Synchronized 和 Lock 的区别

  1. Synchronized 是Java的内置关键字,Lock是一个Java类
  2. Synchronized 无法判断获取锁的状态,而Lock可以
  3. Synchronized 会自动释放锁,Lock必须手动释放,否则死锁
  4. Synchronized 会造成阻塞,Lock不一定会
  5. Synchronized 可重入锁,不可以中断,非公平; Lock 可重入锁,可以判断锁,公平性可以自定义
  6. Synchronized 适合少量代码的同步问题,Lock适合锁大量的同步代码

2.3 精准控制线程顺序

public class ProductAndConsumer02 {

    public static void main(String[] args) {

        Data data = new Data();
        new Thread(() -> {for (int i = 0; i < 10; i++) data.printA();},"A").start();
        new Thread(() -> {for (int i = 0; i < 10; i++) data.printB();},"B").start();
        new Thread(() -> {for (int i = 0; i < 10; i++) data.printC();},"C").start();
    }
}


class Data{

    private static int num = 1;

    private Lock lock = new ReentrantLock();

    private Condition condition1 = lock.newCondition();

    private Condition condition2 = lock.newCondition();

    private Condition condition3 = lock.newCondition();

    public void printA(){
        lock.lock();

        try {
            while (num != 1){
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + ":   "+ "AAAAAAA");
            //num = 2;
            condition2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    public void printB(){
        System.out.println("B lock");
        lock.lock();

        try {
             if (num != 2){
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + ":   "+ "BBBBBBB");
            num = 3;
            condition3.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
    public void printC(){
        lock.lock();

        try {
            while (num != 3){
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName() + ":   "+ "CCCCCCC");
            num = 1;
            condition1.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

}