zoukankan      html  css  js  c++  java
  • JUC 并发编程--01,线程,进程,经典卖票案例, juc的写法

    进程: 就是一个程序, 里面包含多个线程, 比如一个QQ程序
    线程: 进程中最小的调度单元, 比如 QQ中的自动保存功能

    并发: 多个线程操作同一资源, 抢夺一个cpu的执行片段, 快速交替
    并行: 多个线程一起执行

    线程有几个状态: NEW(新) , RUNNABLE(运行) , BLOCKED(阻塞) , WAITING(无限等待) , TIMED_WAITING(超时等待) , TERMINATED(死亡)
    他们之前相互转换关系:

    1、新建(new):线程对象被创建后就进入了新建状态。如:Thread thread = new Thread();
    2、就绪状态(Runnable):也被称为“可执行状态”。线程对象被创建后,其他线程调用了该对象的start()方法,从而启动该线程。如:thread.start(); 处于就绪状态的线程随时可能被CPU调度执行。
    3、运行状态(Running):线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
    4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权限,暂时停止运行。直到线程进入就绪状态,才有机会进入运行状态。阻塞的三种情况:
    ----4.1)等待阻塞:通过调用线程的wait()方法,让线程等待某工作的完成。
    ----4.2)同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),它会进入同步阻塞状态。
    ----4.3)其他阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或超时、或者I/O处理完毕时,线程重新转入就绪状态。
    5、死亡状态(Dead):线程执行完了或因异常退出了run()方法,该线程结束生命周期。

    经典的卖票案例: 直接上代码

    在这里 线程就是单独的 资源类, 属性--方法, 多个线程来操作同一资源, 这样写的好处是解耦

    代码, synchronized 版本的经典的卖票案例

    //这是一个资源类
    class Ticket {
        private int num = 300;
    
        public synchronized void sale(){
            if (num > 0) {
                System.out.println(Thread.currentThread().getName()+"票的剩余个数为" + num--);
            }
        }
    
    
        public static void main(String[] args) {
            //多个线程操作同一资源,  这样写解耦,
            Ticket ticket = new Ticket();
    
            new Thread(()->{
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            },"线程-1").start();
    
            new Thread(()->{
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            },"线程-2").start();
    
            new Thread(()->{
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            },"线程-3").start();
        }
    }
    

    代码, Lock 版本的经典的卖票案例:

    public class LockDemo {
        public static void main(String[] args) {
            Ticket_L tick = new Ticket_L();
            new Thread(()->{for (int i = 0; i < 40; i++) tick.sale();},"thread-1").start();
            new Thread(()->{for (int i = 0; i < 40; i++) tick.sale();},"thread-2").start();
            new Thread(()->{for (int i = 0; i < 40; i++) tick.sale();},"thread-3").start();
        }
    }
    
    //这是一个资源类, 还是卖票案例
    class Ticket_L {
        private int num = 300;
        private Lock lock = new ReentrantLock();
    
        public void sale(){
            //先加一把锁
            lock.lock();
            try {
                if(num > 0){
                    System.out.println(Thread.currentThread().getName()+"票的剩余个数为" + num--);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                //释放锁
                lock.unlock();
            }
        }
    }
    

    synchronized 和 Lock 区别:
    1: synchronized 内置的java关键字, Lock是一个java类
    2: synchronized 不能判断获取锁的状态, Lock 可以判断是否获取到了锁,有个方法: lock.tryLock(), 来判断是否已经加了锁
    3: synchronized 自动释放锁, Lock必须手动释放锁, 不释放的话,容易造成死锁
    4: synchronized 是阻塞的, 比如线程1(获取到锁, 阻塞), 线程2(就等待,一直等待), Lock锁,不一定会一直等下去
    5、Synchronized 可重入锁,不可以中断的,非公平;Lock ,可重入锁,可以 判断锁,非公平(可以自己设置);
    6、Synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的同步代码!

  • 相关阅读:
    移动端rem适配
    extern 关键字
    腾讯2014校园招聘软件开发类笔试试题
    堆,栈,堆栈
    转:对TCP/IP网络协议的深入浅出归纳
    转:程序员面试笔试宝典学习记录(一)
    求素数
    [C++]访问控制与继承(public,protect,private) 有时间再整理!!!
    面向对象的static关键字(类中的static关键字)
    腾讯校园招聘会笔试题2011.10.15
  • 原文地址:https://www.cnblogs.com/lvcai/p/13470197.html
Copyright © 2011-2022 走看看