高级技术之 JUC 高并发编程

本文详细介绍了Java并发编程中的重要工具包JUC,涵盖了JUC的起源、线程概念、并发与并行的区别、管程、用户线程和守护线程的特性。接着,文章深入讨论了Lock接口,对比了synchronized与Lock的异同,强调了CopyOnWriteArrayList的线程安全机制及其优势。此外,文章还讲解了线程间通信、线程安全集合如Vector和Collections的使用,以及多线程锁的概念,如公平锁、非公平锁、可重入锁和死锁。最后,文章探讨了线程池的原理、种类、创建方式以及注意事项,包括线程池参数、拒绝策略和自定义线程池的重要性。
摘要由CSDN通过智能技术生成

1,什么是 JUC

1.1 JUC简介

JUC 就是java.util.concurrent 工具包的简称,这一个专门用来处理线程的工具包,JDK1.5开始出现

请添加图片描述

1.2 进程与线程

**进程(Process):**是系统进行资源分配和调度的基本单位,比如QQ启动就是一个进程。

**线程(Thread):**是操作系统能够进行运算调度的最小单位,是程序执行的最小单位,它被包含在进程中,比如QQ中的各个功能,都是不同的线程。

1.3 线程的状态

在Thread类中枚举了线程的6种状态;

    public enum State {
   
        
        NEW,//新建状态
      
        RUNNABLE,//准备就绪

        BLOCKED,//阻塞状态
      
        WAITING,//等待状态:不见不散

        TIMED_WAITING,//等待状态:过期不候
      
        TERMINATED;//终止态
    }

wait/sleep的区别:

  1. sleep是Thread的静态方法;wait是Object类的方法,任何对象实例都可以调用
  2. sleep不会释放锁,它也不需要占有锁;wait会释放锁,但调用wait方法的前提是当前线程已经占有锁(即代码要在synchronized中)
  3. 它们都可以被interrupted方法中断
1.4 并发和并行
  • 串行:一次只能执行一个任务,只有当前任务执行完成才能执行下一个
  • 并行:多个任务同时执行,最后再进行汇总;比如:泡方便面,电水壶烧水,一边放调料包
  • 并发:同一时刻多个线程访问同一个资源,多个线程对一个点;例子:春运抢票,电商秒杀
1.5 管程

管程(monitor)是保证了同一时刻只有一个进程在管程内活动,JVM中同步是基于进入和退出管程对象来实现的,每一个对象都会有一个管程对象,管程对象会随着java对象一同创建和销毁

执行线程首先要持有管程对象,然后执行完后再释放管程对象,

1.6 用户线程和守护线程

**用户线程:**平时自定义的线程

**守护线程:**运行在后台,是一种特殊的线程,比如垃圾回收

当main主线程结束后,用户线程还在运行,则JVM存活

如果没有用户线程,只剩守护线程,则JVM结束

可以通过Thread的setDaemon(true)方法把用户线程变为守护线程

2,Lock接口

2.1 Synchronized

synchronized 是 Java 中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰一个代码块:被修饰的代码块称为同步语句块,其作用的范围是大括号{}

    括起来的代码,作用的对象是调用这个代码块的对象;

  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用

    的对象是调用这个方法的对象;

    虽然可以使用 synchronized 来定义方法,但 synchronized 并不属于方法定义的一部分,因此,synchronized 关键字不能被继承。如果在父类中的某个方

    法使用了 synchronized 关键字,而在子类中覆盖了这个方法,在子类中的这

    个方法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上

    synchronized 关键字才可以。当然,还可以在子类方法中调用父类中相应的方

    法,这样虽然子类中的方法不是同步的,但子类调用了父类的同步方法,因此,

    子类的方法也就相当于同步了。

  3. 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的

    所有对象;

  4. 修饰一个类,其作用的范围是 synchronized 后面括号括起来的部分,作用主

    的对象是这个类的所有对象。

Lock和synchronized不同:

  1. Lock是一个接口,而synchronized是java中的一个关键字,synchronized是内置语言的实现
  2. synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象;但Lock在发生异常时,必须手动释放锁,很可能造成死锁现象,因此必须在finally中手动释放锁
  3. Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能响应中断
  4. Lock可以知道线程有没有成功获取到锁,而synchronized则无法办到
  5. Lock可以提高多个线程执行读操作的效率

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源

非常激烈时(即有大量线程同时竞争),此时 Lock 的性能要远远优于synchronized

多线程编程步骤:

  1. 创建资源类,创建属性和操作方法
  2. 创建多线程调用资源类的方法
  3. 为了控制多线程执行顺序,在操作方法中:判断,干活,通知

3,线程间通信

场景—两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1,要求用线程间通信

Synchronized:

//创建资源类
class Num{
   
    private int number = 0;
    public synchronized void incr() throws InterruptedException {
   
        while (number != 0){
     //这里一定要用while而不能用if,if会导致假唤醒状态
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+":"+number);
        notifyAll();
    }
    public synchronized void decr() throws InterruptedException {
   
        while (number == 0){
   
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+":"+number);
        notifyAll();
    }
}

public class SynchronizedDemo {
   
    public static void main(String[] args) {
   
        Num num = new Num();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.incr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"AA").start();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.decr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"BB").start();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.incr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"CC").start();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.decr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"DD").start();
    }
}

Lock:

//创建资源类
class Num1{
   
    private int number = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void incr() throws InterruptedException {
   
        lock.lock();
        try {
   
            while (number != 0){
   
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+":"+number);
            condition.signalAll();
        } finally {
   
            lock.unlock();
        }
    }
    public void decr() throws InterruptedException {
   
        lock.lock();
        try {
   
            while (number == 0){
   
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+":"+number);
            condition.signalAll();
        } finally {
   
            lock.unlock();
        }
    }
}


public class LockDemo {
   
    public static void main(String[] args) {
   
        Num1 num = new Num1();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.incr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"AA").start();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.decr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"BB").start();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.incr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"CC").start();
        new Thread(()->{
   
            for (int i = 0; i < 10; i++) {
   
                try {
   
                    num.decr();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
        },"DD").start();
    }
}

定制线程通信顺序:

1->5,1->10,1->15 执行三轮

//资源类
class Resource{
   
    private int flag = 1;//标志位
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();
    public void circle5(int loop) throws InterruptedException {
   
        lock.lock();
        try {
   
            while (flag != 1){
   
                c1.await();
            }
            for (int i = 1; i < 6; i++) {
   
                System.out.println(Thread.currentThread().getName()+":"&
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值