JUC详解1

JUC详解1

JUC:java.util.concurrent

线程和进程
1、进程是指的一个程序,如一个qq.exe、IDEA.exe等
2、线程指打开一个进程后,如qq可打字发消息,这就是线程

一个进程往往含有多个线程(最少一个)
java默认含有2个线程:main、GC
java的三种开线程的方式:Thread、Runable、Callable

并发、并行
并发:多个线程操作同一个资源

  • CPU一核:通过模拟多个线程,交替进行

并行:多个线程同时执行

  • CPU多核:多个线程同时执行
//查询自己电脑的核数
System.out.println(Runtime.getRuntime().availableProcessors());

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

线程

线程的状态

新生:NEW
运行:RUNNABLE
阻塞:BLOCKED
等待:WAITING
超时等待:IMED_WAITING
终止:TERMINATED

wait/sleep

wait–>Object(包不同)
wait会自己释放锁(锁的释放方式)
必须在同步代码块中(使用范围)
不需要捕获异常(异常的捕获)
sleep–>Thread
sleep不会自己释放锁
可以在任何地方使用
需要捕获异常

lock锁

看个栗子

public class Sync {
    public static void main(String[] args) {
        //线程就是一个单独的资源类,没有附属任何操作
        Ticket ticket = new Ticket();

        for (int i=0;i<50;i++){
            new Thread(()->{ticket.sale();},"A").start();
            new Thread(()->{ticket.sale();},"B").start();
            new Thread(()->{ticket.sale();},"C").start();
        }
    }
}
/**
 * 资源类
 */
class Ticket{

    private int number=50;
    public void sale(){
        if (number > 0) {
            System.out.println(Thread.currentThread().getName()+"这是第"+number--+"张票;还剩:"+number+"张票。");
        }
    }
}

运行情况:
在这里插入图片描述
运行的很乱,没有顺序,而且还出现了-1;

	解决的原始方案:加synchronize
 public synchronized void sale(){
        if (number > 0) {
            System.out.println(Thread.currentThread().getName()+"这是第"+number--+"张票;还剩:"+number+"张票。");
        }
    }

在这里插入图片描述

			lock

在这里插入图片描述
在这里插入图片描述
可重入锁:ReentrantLock
在这里插入图片描述
默认为非公平锁:非公平锁,即有多个线程,那个线程执行块,执行那个
公平锁:一个一个,排队来,先来后到,非常公平;
但我们实际中都使用非公平锁;为什么呢?

  • 你想一个线程需要2小时执行完,一个线程2秒执行完,如果公平,2小时的排在2秒的前,那么就得要先执行完两小时的,再等2秒的,这样肯定不太行

使用lock实现

public class LockTest {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        for (int i=0;i<50;i++){
            new Thread(()->{ ticket.sale(); },"11").start();
            new Thread(()->{ ticket.sale(); },"22").start();
            new Thread(()->{ ticket.sale(); },"33").start();
        }
    }
}

/**
 * lock三步曲
 * 1、new ReentrantLock();
 * 2、加锁:lock.lock();
 * 3、解锁:lock.unlock();
 */
class Ticket{
    private int number=50;
    Lock lock = new ReentrantLock();
    public  void sale(){
        //加锁
        lock.lock();
        try {
            //业务代码
            if (number > 0) {
                System.out.println(Thread.currentThread().getName()+"这是第"+number--+"张票;还剩:"+number+"张票。");
            }
        }catch (Exception e){
        e.printStackTrace();
        }finally {
            //解锁
            lock.unlock();
        }
    }
}

在这里插入图片描述

		synchronized和lock的区别
  1. synchronized是一个java的内置的关键字,而lock是一个java类
  2. synchronized无法判断锁的状态,而lock可以判断是否获取到
  3. synchronized是全自动的,会自动加锁释放锁;lock必须手动释放锁,否则会出现死锁
  4. synchronized:线程1(获得锁,阻塞),线程2(等待,直到线程1释放锁);lock:可以获取锁:lock.tryLock();
  5. synchronized:可重入锁,非公平,不可中断;lock:可重入锁,非公平(可自由设置),可以判断锁的状态;
  6. synchronized:适合使用锁少量代码同步问题;lock:适合锁大量同步代码

补充
可重入锁是指:同一个线程可以获取同一把锁多次
重入锁实现可重入性原理或机制是:每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。

下一篇:JUC详解2——生产者消费者

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值