美文网首页Java基础相关
JAVA基础-多线程和锁

JAVA基础-多线程和锁

作者: 来lol里 | 来源:发表于2021-01-07 15:58 被阅读0次
    • 线程的基本流程

      image.png
    • 如何中断一个线程
      方法一:调用interrupt方法,通知线程应该中断了:
      A.如果线程处于被阻塞状态,那么线程将立即退出被阻塞状态,并抛出了一个InterruptedException异常。
      B.如果线程处于正常活动状态,那么会将该线程的中断标志设置为true。被设置中断标志的线程将正常运行,不受影响。
      方法二:使用volatile boolean类型变量控制;

    • 对象锁和类锁的区别
      java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,知道线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。
      java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的。

    对象锁一般有三种
    1.锁非静态变量,非静态变量是实例自身变量,不会与其他实例共享,所以锁住实体内声明的非静态变量可以实现对象锁。锁住同一个变量的方法块共享同一把锁

      private Object obj =new Object();
      public void testSynchronized(){
            synchronized (obj);
            //do sth
    
        }
    

    2.锁非静态方法,这个就比较直观了

      public synchronized void  testSynchronized(){
            //do sth
        }
    

    3.锁this,this 指的是当前对象实例本身,所以,所有使用 synchronized(this)方式的方法都共享同一把锁。

     public void testSynchronized(){
            synchronized (this);
            //do sth
        }
    

    类锁是加载类上的,而类信息是存在 JVM 方法区的,并且整个 JVM 只有一份,方法区又是所有线程共享的,所以类锁是所有线程共享的,同一时刻,只能有一个线程使用加了锁的方法或方法体,不管是不是同一个实例。
    1.锁静态变量

        static Object obj =new Object();
    public  void  testSynchronized(){
            synchronized(obj);
            //do sth
        }
    

    2.锁静态方法

       public static synchronized void  testSynchronized(){
            //do sth
        }
    

    3.锁xxx.class

      public static  void  testSynchronized(){
            synchronized (MainActivity.class){
                //do sth
            }
           
        }
    
    • wait()、sleep()和yield()的区别
      sleep()和yield()方法是定义在Thread类中,而wait()方法是定义在Object类中的。
      wait()和sleep()的关键的区别在于,wait()是用于线程间通信的,而sleep()是用于短时间暂停当前线程,而且wait()会释放锁,sleep()和yield()不会释放锁 。
      yield()与wait()和sleep()方法有一些区别,它仅仅释放线程所占有的CPU资源,从而让其他线程有机会运行,但是并不能保证某个特定的线程能够获得CPU资源,注意这里仅仅是让出CPU的执行权,但是并没有释放锁的,谁能获得CPU完全取决于调度器,在有些情况下调用yield方法的线程甚至会再次得到CPU资源。所以,依赖于yield方法是不可靠的,它只能尽力而为。

    • ReentrantLock(可重入锁)
      可重入性:ReentrantLock字面意思即为再进入锁,称为可重入锁,其实synchronize所使用的锁也是可以重入的,两者关于这个区别不打,它们都是同一个线程进入一次,锁的计数器进行自增,要等到锁的计数器下降为零时,才能释放锁。
      在synchronized优化以前,性能比ReentrantLock差很多,但自从synchronize引入了偏向锁、轻量级锁(自选锁)后 ,也就是自循锁后,两者性能差不多(JDK1.6以后,为了减少获得锁和释放锁所带来的性能消耗,提高性能,引入了“轻量级锁”和“偏向锁”)。在两种场景下都可以使用,官方更推荐使用synchronized,因为写法更容易。synchronized的优化其实是借鉴了ReentrantLock中的CAS技术,都是试图在用户态就把加锁问题解决,避免进入内核态的线程阻塞

    • 公平锁和非公平锁
      公平锁需要上下挂起,耗费性能。每一个先来的线程都可以最先获取到锁,但是增加了上下文切换与等待线程的状态变换时间。所以效率相较于非公平锁较慢

    • 线程池

      图片1.png
    public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    

    任务来了首先进入到corePoolSize中,如果核心线程满了,进入workQueue队列里等待,如果队列满了,进入maximumPoolSize中等待,如果线程继续增加,则走handler(线程饱和策略)执行具体的饱和策略(默认四种
    ThreadPoolExecutor.AbortPolicy 丢弃任务,抛出异常
    ThreadPoolExecutor.DiscardPolicy丢弃任务,不过也不抛出异常,
    ThreadPoolExecutor.CallerRunsPolicy该任务被线程池拒绝,由调用线程处理该任务 。ThreadPoolExecutor.DiscardOldestPolicy 抛弃队列最前面的任务,然后重新尝试执行任务)。
    keepAliveTime表示空闲线程存活时间。

    四种线程池的创建方式
    通过Executors提供四种线程池,分别为:
    newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
    newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

    阿里推荐是用ThreadPoolExecutor自己创建,因为FixedThreadPool和SingleThreadExecutor => 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而引起OOM异常
    CachedThreadPool => 允许创建的线程数为Integer.MAX_VALUE,可能会创建大量的线程,从而引起OOM异常
    这就是为什么禁止使用Executors去创建线程池,而是推荐自己去创建ThreadPoolExecutor的原因。
    合理配置线程池参数:CPU密集型,IO密集型,混合型。

    • volatile关键字
      保证可见性 不保证唯一性。使用时候只有保证全局只有唯一写入的地方时候可用。
      image.png

    相关文章

      网友评论

        本文标题:JAVA基础-多线程和锁

        本文链接:https://www.haomeiwen.com/subject/lxznoktx.html