从零开始学架构(3)--juc笔记

juc是java util concurrent的简写,即java原生的并发包。
要明白java并发包,必须要先理解并发和并行的区别

并发和并行的区别

**并发:**指的是多个线程对同一个资源交替执行的过程。
**并行:**指的是多个线程同时执行。

线程的6种状态

java源码可知,线程有6种状态即NEW(新建) RUNNABLE( 运行) BLOCKED (阻塞) WATTING(等待)延迟等待(TIMED_WATTING)终止(TERMINATED)

在这里插入图片描述

wait/sleep的区别

  • 类不同
    wait:Obejct类的方法
    sleep是thread类的方法
    线程中的休眠一般不使用上述方法 一般适用TimeUnit.SECONDS.sleep(3). (休眠三秒)

  • 会不会释放资源
    sleep抱着锁睡觉,不释放
    wait会释放

  • 适用范围不同
    wait和notify是一组,一般线程通讯使用
    sleep是一个单独的方法,在哪里都可以用

  • 关于异常
    sleep需要捕获异常

关键点:lock锁

synchronized锁是非LOCK锁,是比较传统的方式,然而不适合常用。
synchronize锁和lock锁的区别:lock锁是一个对象,synchronized是一个关键字,synchronized会自动释放锁,lock锁需要手动释放锁。从而会造成,如果A线程死锁,使用synchronized的线程B会一直等待下去,但是Lock可以通过尝试获取锁,失败就会放弃。
在代码量比较大的时候,一般适用Lock精准控制锁。

synchronized版
写并行线程的思路一句话总结:线程操作资源类(符合设计模式不耦合的原则)
public class Demo01 {
public static void main(String[] args) throws InterruptedException {
// 1、新建资源类
Ticket ticket = new Ticket();

    // 2、线程操纵资源类
    new Thread(new Runnable() {
        public void run() {
            for (int i = 1; i <=40; i++) {
                ticket.saleTicket();
            }
        }
    },"A").start();


    new Thread(new Runnable() {
        public void run() {
            for (int i = 1; i <=40; i++) {
                ticket.saleTicket();
            }
        }
    },"B").start();

    new Thread(new Runnable() {
        public void run() {
            for (int i = 1; i <=40; i++) {
                ticket.saleTicket();
            }
        }
    },"C").start();
}

}

// 单独的资源类,属性和方法!
// 这样才能实现复用!
class Ticket{

private int number = 30;

// 同步锁,厕所 =>close=>
// synchronized 这是一个关键字
public synchronized void saleTicket(){
    if (number>0){
        System.out.println(Thread.currentThread().getName() + "卖出第"+(number--)+"票,还剩:"+number);
    }
}

}

如果是LOCK锁 只需要对资源类进行略改动

class Ticket{

private Lock lock. =new ReentrantLock()
private int number = 30;

// 同步锁,厕所 =>close=>
// synchronized 这是一个关键字
public  void saleTicket(){
lock.lock();//加锁

try{
if (number>0){
System.out.println(Thread.currentThread().getName() + “卖出第”+(number–)+“票,还剩:”+number);
}
}catch(Exception){
e.printStackTrace();
}finally{
lock.unlock();//手动解锁
}
}
}

如何用synchronized写消费者生产者模式呢?还是三步走线程操纵资源类,不过在写资源类的时候需要有唤醒其他线程的操作,会用到wait notify成对的操作。(资源类的写法也是三步骤1.判断,执行,通知,即判断是否需要休眠,如果不需要就执行,执行完通知其他线程)

如synchronized版
package com.coding.demo01;

// Synchronized 版
/*
目的: 有两个线程:A B ,还有一个值初始为0,
实现两个线程交替执行,对该变量 + 1,-1;交替10次
*/
public class Demo03 {
public static void main(String[] args) {
Data data = new Data();

    // +1
    new Thread(()->{
        for (int i = 1; i <=10 ; i++) {
            try {
                data.increment();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    },"A").start();

    // -1
    new Thread(()->{
        for (int i = 1; i <=10 ; i++) {
            try {
                data.decrement();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    },"B").start();


}

}

// 资源类
// 线程之间的通信: 判断 执行 通知
class Data{

private int number = 0;

// +1
public synchronized void increment() throws InterruptedException {
    while (number!=0){ // 判断是否需要等待
        this.wait();
    }
    number++; // 执行
    System.out.println(Thread.currentThread().getName()+"\t"+number);
    // 通知
    this.notifyAll(); //唤醒所有线程
}

// -1
public synchronized void decrement() throws InterruptedException {
    while(number==0){ // 判断是否需要等待
        this.wait();
    }
    number--; // 执行
    System.out.println(Thread.currentThread().getName()+"\t"+number);
    // 通知
    this.notifyAll(); //唤醒所有线程
}

}

上述是两个线程的消费者和生产者模式,如果有三个或者是三个以上的线程交替进行显然就不行了,因为上面notifyall()是唤醒其他休眠的线程,没有指定唤醒某个线程,如果线程比较的话,就会乱套。如果需要精准唤醒某个线程需要使用ReentrantLock类中的Condition类的await(休眠) signal(唤醒)

public class Demo04 {
public static void main(String[] args) {
Data2 data = new Data2();

    new Thread(()->{
        for (int i = 1; i <= 10; i++) {
            try {
                data.print5();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    },"A").start();

    new Thread(()->{
        for (int i = 1; i <= 10; i++) {
            try {
                data.print10();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    },"B").start();

    new Thread(()->{
        for (int i = 1; i <= 10; i++) {
            try {
                data.print15();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    },"C").start();
}

}

// 资源类
class Data2{
private int number = 1; // 1A 2B 3C
private Lock lock = new ReentrantLock();
// 实现精准访问
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();

public void print5() throws InterruptedException {

    lock.lock();

    try {
        // 判断
        while (number!=1){
            condition1.await();
        }
        // 执行
        for (int i = 1; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + "\t" + i);
        }
        // 通知第二个线程干活!
        number = 2;
        condition2.signal(); // 唤醒
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock(); // 一定要解锁
    }
}

public void print10() throws InterruptedException {
    lock.lock();
    try {
        // 判断
        while (number!=2){
            condition2.await();
        }
        // 执行
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName() + "\t" + i);
        }
        // 通知3干活
        number = 3;
        condition3.signal();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }

}

public void print15() throws InterruptedException {
    lock.lock();
    try {
        // 判断
        while (number!=3){
            condition3.await();
        }
        // 执行
        for (int i = 1; i <= 15; i++) {
            System.out.println(Thread.currentThread().getName() + "\t" + i);
        }
        // 通知 1 干活
        number = 1;
        condition1.signal();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值