JUC(一)线程、进程、synchronized、LOCK、锁的对象

什么是JUC

JUC是java.util.concurrent的简写。

JUC

java2个默认线程:main、GC

线程和进程

进程:一个应用程序就会启动一个进程

线程:一个进程中会有多个至少1个线程。

Java无法直接创建线程,直接操作硬件,都是定错C++做的

并发:多线程操作同一个资源(CPU1核,模拟多条线程)

并行:多个线程同时执行(CPU多核,多个线程可以同时执行)

package com.xiaobai.demo01;
//打印电脑CPU核数
//CPU 密集型,IO密集型
public class Test1 {
    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().availableProcessors());
    }
}

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

Lock锁

回顾synchronized

package com.xiaobai.demo01;

public class Test1 {
    public static void main(String[] args) {
        Stick stick = new Stick();
        new Thread(()->{
            for (int i = 0; i < 200; i++) {
                stick.sale();
            }
        },"a").start();
        new Thread(()->{
            for (int i = 0; i < 200; i++) {
                stick.sale();
            }
        },"b").start();
        new Thread(()->{
            for (int i = 0; i < 200; i++) {
                stick.sale();
            }
        },"c").start();
    }
}


class Stick {
    private int sticknums = 200;

    public synchronized void sale() {
        if (sticknums>0){
            System.out.println(Thread.currentThread().getName()+"售票成功,票为:" + (sticknums--) + ",余票:" + sticknums);
        }
    }
}

LOCK锁

ReentrantLock()

无参:非公平锁,默认

有参:(true)公平锁

package com.xiaobai.demo01;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test2 {
    public static void main(String[] args) {
        Stick2 stick2 = new Stick2();
        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                stick2.sale();
            }
        },"a").start();
        new Thread(()->{
            for (int i = 0; i < 200; i++) {
                stick2.sale();
            }
        },"b").start();
        new Thread(()->{
            for (int i = 0; i < 200; i++) {
                stick2.sale();
            }
        },"c").start();
    }

}

class Stick2 {
    private int sticknums = 200;
    Lock l = new ReentrantLock();
    public void sale() {
        l.lock();//加锁
        try {
            if (sticknums>0){
                System.out.println(Thread.currentThread().getName()+"售票成功,票为:" + (sticknums--) + ",余票:" + sticknums);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            l.unlock();//解锁
        }

    }
}

synchronized 和lock的区别

  1. synchronized 内置的Java关键字,Lock是一个Java类
  2. synchronized 无法判断获取锁的庄爱,lock可以判断是否获取到了锁
  3. synchronized 会自动释放锁,lock必须手动释放锁,如果不释放,就是死锁
  4. synchronized 线程1获得锁,如果阻塞,那么线程2就要一直等待。lock不会一直等待下去
  5. synchronized 可重入锁,非公平,lock,可重入锁,可以判断锁,是否公平可自己设置
  6. synchronized 试用少量代码块,lock试用大量

生产者消费者问题,等待唤醒、虚假唤醒

package com.xiaobai.pc;
/*
* 线程之间的通信问题,生产者和消费者问题  等待唤醒  通知唤醒
* 线程交替执行,A B操作同一个变量 num = 0
* A num+1
* B num-1
*
* */
public class A {
    public static void main(String[] args){
        Date date = new Date();
        new Thread(()->{
            try {
                for (int i = 0; i < 20; i++) {
                    date.increment();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"a").start();
        new Thread(()->{
            try {
                for (int i = 0; i < 20; i++) {
                    date.decrement();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"b").start();
    }
}


class Date{//数字   资源类
    private int number = 0;
    public synchronized void increment() throws InterruptedException {
        if(number!=0){
            //等待
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"--->增加--->"+number);
        //通知其他线程增加完毕
        this.notify();
    }
    public synchronized void decrement() throws InterruptedException {
        if(number==0){
            //等待
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"--->减少--->"+number);
        //通知其他线程减完毕
        this.notify();
    }

    //+1
    //-1
}

问题:怎样解决3个线程以上使用(虚假唤醒问题)

解决方法:if改为while

package com.xiaobai.pc;
/*
* 线程之间的通信问题,生产者和消费者问题  等待唤醒  通知唤醒
* 线程交替执行,A B操作同一个变量 num = 0
* A num+1
* B num-1
*
* */
public class A {
    public static void main(String[] args){
        Date date = new Date();
        new Thread(()->{
                for (int i = 0; i < 40; i++) {
                    try {
                        date.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        },"a").start();
        new Thread(()->{
                for (int i = 0; i < 40; i++) {
                    try {
                        date.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        },"b").start();
        new Thread(()->{
                for (int i = 0; i < 40; i++) {
                    try {
                        date.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        },"c").start();
        new Thread(()->{
                for (int i = 0; i < 40; i++) {
                    try {
                        date.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        },"d").start();
    }
}


class Date{//数字   资源类
    private int number = 0;
    public synchronized void increment() throws InterruptedException {
        while(number!=0){
            //等待
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"--->增加--->"+number);
        //通知其他线程增加完毕
        this.notifyAll();
    }
    public synchronized void decrement() throws InterruptedException {
        while(number==0){
            //等待
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"--->减少--->"+number);
        //通知其他线程减完毕
        this.notifyAll();
    }

    //+1
    //-1
}
posted @ 2021-05-13 16:48  77的小白  阅读(105)  评论(0)    收藏  举报