JUC并发编程

JUC并发编程

Java.util工具包

Java.util.concurrent

业务:普通的线程代码Thread

Runnable没有返回值,效率比Callable相对较低

以前学的里面:Callable、ReentrantLock等都是java.util.concurrent包里面的

线程和进程

进程:一个程序

一个进程可以包含多个线程,至少包含一个线程

java默认有两个线程,main和GC

线程:

Java真的可以开启线程吗?不可以

​ 只能通过本地方法去调用底层C++,Java无法直接操作硬件

private native void start0();

并发和并行

并发才存在多线程的说法,多线程操作同一个资源

  • CPU一核,模拟出来多条线程,快速交替产生的假象

并行:多个人一起行走

  • CPU多核,多个线程可以同时执行;线程池
  • 获取CPU核数 Runtime.getRunTime().avaliableProcessors()

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

线程的六个状态

NEW, RUNNABLE, BLOCKED, WAITING死等, TIMED_WAITING超时等待, TERMINATED

wait/sleep区别

  1. 来自不同的类 wait-object类、sleep-Thread类

    企业中一般用TimeUnit.DAYS.sleep(1); 属于JUC包

  2. 锁的释放:wait会释放锁,sleep抱着锁睡,不释放

  3. 使用范围不同:wait只能在同步代码块中使用,sleep可以在任何地方

  4. 捕获异常:wait不需要,sleep需要捕获异常

lock锁(重点)

传统 synchronized
/*
真正的多线程开发,公司中的开发,降低耦合性
线程就是一个单独的资源类,没有任何附属的操作
1.属性、方法
*/

public class SaleTicketDemo1{
  public static void main(String[] args){
    //并发:多线程操作同一个资源类,把资源类丢入线程
    Ticket ticket = new Ticket();
    
    new Thread(()->{
      for(int i=1; i<50; i++){
        ticket.sale();
      }
    },"A").start();
    new Thread(()->{
      for(int i=1; i<50; i++){
        ticket.sale();
      }
    },"B").start();
    new Thread(()->{
      for(int i=1; i<50; i++){
        ticket.sale();
      }
    },"C").start();
  }
}

//资源类 OOP
class Ticket{
  //属性、方法
  private int number = 40;
  //synchronized本质:队列,锁
  public synchronized void sale(){
    if(number > 0){
      System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票");
    }
  }
}
Lock接口

三个实现类:ReentrantLock(常用),ReadLock,WriteLock

public class SaleTicketDemo2{
  public static void main(String[] args){
    //并发:多线程操作同一个资源类,把资源类丢入线程
    Ticket2 ticket = new Ticket2();
    new Thread(()->{for(int i=1; i<50; i++) ticket.sale();},"A").start();
    new Thread(()->{for(int i=1; i<50; i++) ticket.sale();},"B").start();
    new Thread(()->{for(int i=1; i<50; i++) ticket.sale();},"C").start();
  }
}

//资源类 OOP
class Ticket2{
  //属性、方法
  private int number = 40;
  
  Lock lock = new ReentrantLock();
  
  public void sale(){
    lock.lock();//加锁
    try{
    	if(number > 0){
      	System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票");
    	}
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      lock.unlock();//解锁 
    }
  }
}

公平锁&非公平锁

公平锁:必须先来后到

非公平锁(默认) :可以插队,根据CPU分配

Lock和synchronized的区别
  1. synchronized是内置的Java关键字,lock是Java类

  2. synchronized无法判断获取锁的状态,lock可以判断是否获取到了锁

  3. synchronized会自动释放锁,lock锁必须手动释放锁,不释放会造成死锁

  4. synchronized线程1(获得锁但是阻塞)线程2(一直等待),lock锁不一定会一直等待

    lock.trylock(); 尝试获取锁

  5. synchronized可重入锁,不可以中断的,非公平锁,lock可重入锁,可以判断锁,非公平锁(可以自己设置)

  6. synchronized适合锁少量的代码同步问题,lock适合锁大量的同步代码

锁是什么?如何判断锁的是谁

posted @ 2021-02-23 10:38  GladysChloe  阅读(49)  评论(0)    收藏  举报