JUC初步理解(一)

JUC是java.util.concurrent工具包的简称,是一个处理线的工具包

进程与线程

进程:程序的运行过程
线程:操作系统进行运行调度的最小单位,被包含在进程中,是进程中运行的实际单位
进程与线程的关系,比如电脑开了一个文档,文档运行就是进程,文档中打字,查找,等等操作就是线程。

wait/sleep的区别

来自不同的类:wait=>Object sleep=>Thread
关于锁的释放:wait会释放,sleep抱着锁睡觉,不会释放
使用范围不同:wait必须在同步代码块中,sleep哪都能睡
是否需要捕获异常:wait不需要捕获异常,sleep需要捕获异常
JUC源码得出他们都需要捕获异常

sychronized 和 lock

关于线程同步,需要牢牢记住的第一点是:线程同步就是线程排队。同步就是排队。线程同步的目的就是避免线程“同步”执行。这可真是个无聊的绕口令。
关于线程同步,需要牢牢记住的第二点是 “共享”这两个字。只有共享资源的读写访问才需要同步。如果不是共享资源,那么就根本没有同步的必要。
关于线程同步,需要牢牢记住的第三点是,只有“变量”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下,线程之间就需要同步。
关于线程同步,需要牢牢记住的第四点是:多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码;无论是否执行同一份代码,只要这些线程的代码访问同一份可变的共享资源,这些线程之间就需要同步。

sychronized和lock的区别

Synchronized是关键字,lock是类
Synchronized会自动释放锁,lock必须手动释放锁,否则会发生死锁
Synchronized无法判断锁的状态,lock可以判断是否获得锁
比如A线程(获得锁),阻塞,Synchronized的话B线程会傻傻的等待;lock锁B线程不一定会一直等待
Synchronized 可重入锁 ,不可中断,非公平;lock 可重入锁,可以判断锁状态,默认非公平,可修改
Synchronized 适合少量线程同步问题,lock适合大量同步代码

消费者与生产者

传统的生产者与消费者问题

package com.boom.example.demo.aa;

public class pc {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for(int i=1;i<=10;i++){
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(()->{
            for(int i=1;i<=10;i++){
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(()->{
            for(int i=1;i<=10;i++){
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"c").start();
        new Thread(()->{
            for(int i=1;i<=10;i++){
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"d").start();
    }
}
//判断等待,业务,通知
class Data{
    private int number = 0;

    public synchronized void increment() throws InterruptedException {
    //如果是if会虚假唤醒
        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();
    }
}

lock版的

class Data{
    private int number = 0;
    Lock lock =new ReentrantLock();
    Condition condition=lock.newCondition();

    public  void increment() throws InterruptedException {
        try {
            lock.lock();
            while (number !=0){
               condition.await();
            }
            number++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public  void decrement() throws InterruptedException {
        try {
            lock.lock();
            while (number ==0){
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

condition的精准实现

 private Lock lock = new ReentrantLock();//新建锁
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();

8锁的现象

1.多个线程使用同一把锁,顺序执行

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile = new Mobile();
        new Thread(()->{
            mobile.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        new Thread(()->{
            mobile.sendMS();
        }).start();

    }

}
class Mobile{
    public synchronized void sendEmail(){
        System.out.println("sendEmail");//先输出
    }
    public synchronized void sendMS(){
        System.out.println("sendMS");
    }
}

2.多个线程使用同一把锁,使其中某个线程阻塞,还是顺序执行

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile = new Mobile();
        new Thread(()->{
            mobile.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            mobile.sendMS();
        }).start();

    }

}
class Mobile{
    public synchronized void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendEmail");//先执行
    }
    public synchronized void sendMS(){
        System.out.println("sendMS");
    }
}

3.多个线程有锁与没有锁,随机执行

两者不存在竞争同一把锁,执行顺序是随机的

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile = new Mobile();
        new Thread(()->{
            mobile.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            mobile.sendMS();
        }).start();

        new Thread(()->{
            mobile.getWeixinMs();
        }).start();
    }

}
class Mobile{
    public synchronized void sendEmail(){
        System.out.println("sendEmail");
    }
    public synchronized void sendMS(){
        System.out.println("sendMS");
    }
    public void getWeixinMs() {
        System.out.println("getWeixinMs");
    }
}

4.多个线程使用多把锁,随机执行

被synchronized修饰的方法,锁的对象是方法调用者
调用者不同,他们的锁不同,相互没有关系

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile1 = new Mobile();
        Mobile mobile2 = new Mobile();
        new Thread(()->{
            mobile1.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            mobile2.sendMS();
        }).start();


    }

}
class Mobile{
    public synchronized void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendEmail");
    }
    public synchronized void sendMS(){
        System.out.println("sendMS");
    }
}

5Class锁,多个线程使用一个对象,顺序执行

被synchronized和static同时修饰的方法锁的对象是类的class对象,线程顺序执行
锁class和锁对象的区别
class,类模板只有一个
对象锁,通过类模板可以new多个对象
如果是锁class,那new的对象都是同一把锁

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile = new Mobile();
        new Thread(()->{
            mobile.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            mobile.sendMS();
        }).start();


    }

}
class Mobile{
    public synchronized static void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendEmail");
    }
    public synchronized static void sendMS(){
        System.out.println("sendMS");
    }
}

6多个线程使用多个对象,顺序执行

被 synchronized 修饰 和 static 修饰的方法,锁的对象是类的 class 对象,是唯一的一把锁。
Class锁是唯一的,所以多个对象使用的也是同一个Class锁

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile1 = new Mobile();
        Mobile mobile2 = new Mobile();
        new Thread(()->{
            mobile1.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            mobile2.sendMS();
        }).start();


    }

}
class Mobile{
    public synchronized static void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendEmail");
    }
    public synchronized static void sendMS(){
        System.out.println("sendMS");
    }
}

7class锁与对象锁,多个线程使用一个对象,随机执行

被 synchronized和static修饰的方法,锁的对象是类的class对象!唯一的同一把锁;
只被synchronized修饰的方法,是普通锁(如对象锁),不是Class锁,所以进程之间执行顺序互不干扰。

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile = new Mobile();
        new Thread(()->{
            mobile.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            mobile.sendMS();
        }).start();


    }

}
class Mobile{
    public synchronized static void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendEmail");
    }
    public synchronized  void sendMS(){
        System.out.println("sendMS");
    }
}

8 class锁与对象锁,多个线程使用多个对象,随机执行

package com.boom.example.demo.aa;

import java.util.concurrent.TimeUnit;

public class MultiThreadUseOneLock01 {
    public static void main(String[] args) {
        Mobile mobile1 = new Mobile();
        Mobile mobile2 = new Mobile();
        new Thread(()->{
            mobile1.sendEmail();
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            mobile2.sendMS();
        }).start();


    }

}
class Mobile{
    public synchronized static void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendEmail");
    }
    public synchronized  void sendMS(){
        System.out.println("sendMS");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值