关于java:Java并发Java线程

大家好,这里是淇妙小屋,一个分享技术,分享生存的博主
以下是我的主页,各个主页同步更新优质博客,创作不易,还请大家点波关注
掘金主页
知乎主页
Segmentfault主页
开源中国主页
后续会公布更多MySQL,Redis,并发,JVM,分布式等面试热点常识,以及Java学习路线,面试重点,职业规划,面经等相干博客
转载请表明出处!

0. Java线程面试题

0.1 线程占用的内存

  • JDK1.4默认单个线程占用256K
  • JDK1.5默认单个线程占用1M
  • 能够通过-Xss参数设定

0.2 为什么要应用线程池

  • 手动创立线程池的毛病

    • 不受危险管制:服务器CPU资源无限,如果每个人都显示手动创立线程,不晓得哪里的代码呈现了多线程,在运行的时候所有线程都在抢占资源,不好管制
    • 频繁创立,开销大
    • 不好治理:可能无限度新建线程,可能占用过多系统资源导致死机或OOM。而重用存在的线程,缩小对象创立、沦亡的开销,性能佳
  • 线程池长处

    • 升高系统资源耗费,通过重用已存在的线程,升高线程创立和销毁造成的耗费
    • 进步零碎响应速度,当有工作达到时,通过复用已存在的线程,无需期待新线程的创立便能立刻执行
    • 不便线程并发数的管控

1. 线程的状态

1.1 线程状态枚举

  • NEW

    线程被构建,还未start

  • RUNNABLE

    运行状态

  • BLOCKED

    阻塞状态,阻塞于锁

  • WAITING

    期待状态

  • TIME_WAITING

    超时期待状态,超过工夫自行返回

  • TERMINATED

    终止状态,示意线程执行结束

1.2 线程状态转换图

2. 守护线程和线程优先级

2.1 守护线程

JVM中不存在非守护线程时,JVM会退出

2.2 线程的优先级

创立线程的时候能够给线程设置优先级,优先级高的线程有更高的概率调配到更多的工夫片(不相对)

3. 线程中断

能够了解为Thread有个interrupted标识符,默认为false,示意一个线程是否被其余线程进行了中断操作

public void interrupt();//将Thread的示意符设为false
public void isInterrupted();//返回标识符
public static isInterrupted();//返回标识符,并设为false

如果线程抛出InterruptedException,那么在抛出InterruptedException之前,JVM会先将标识符设为false,而后再抛出

4. 线程间通信

4.1 通过volatile和synchronized

4.2 期待/告诉机制

  • sleep()

    以后线程进入TIME_WAITING状态,不会开释锁,但会开释CPU资源

    一段时间后昏迷,回到RUNNABLE状态

  • yield()

    以后线程由RUNNING状态变为READY状态,不会开释锁,但会开释CPU资源

  • wait(),notify(),nitifyAll()

    • 应用wait(),notify(),nitofyAll()时须要对调用对象加锁(必须在同步代码块内)
    • 以后线程调用某个加锁对象的wait()后,会进入该对象的monitor对象的期待队列中,开释锁,开释CPU资源状态变为WAITING
    • 以后线程调用某个加锁对象的notify()或nitifyAll(),期待队列中的线程从期待队列中挪动到同步队列中,线程状态由WAITING变为BLOKING

      期待队列中的线程要想从wait()中返回,除了须要有其余线程调用notify()外,还须要期待线程开释锁,取得对象的锁后能力从wait()返回

  • join()

    留神,wait()是Object的,join()是Thread的

    join()中底层调用的wait()

    若调用了thread2.join()

    就是让以后线程进入thread2的monitor对象的期待队列中,晓得thread2完结才会被唤醒

    因为底层调用的是wait(),所以会开释锁,但留神开释的是thread2的锁

4.3 期待/告诉标准

  • 期待方伪代码

    synchronized(对象){
        while(条件不满足){
            对象.wait();
        }
        对应的解决逻辑
    }
  • 告诉方伪代码

    synchronized(对象){
        扭转条件
        对象.nitify();
    }

5. 创立线程的形式

1. 继承Thread

2. 实现Runnable接口/利用匿名对象/lambda表达式

3. 实现Callable接口

4. FutureTask(能够由调用线程执行其run(),也能够作为工作提交给线程池)

5. 定时器

6. Stream的parallelStream

7. 线程池隐性创立

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理