多线程_基础

一.一个Java程序最少开几个线程?

  • 3个:主线程;gc线程;异常处理线程

二.线程的生命周期以及状态?

 

阻塞的分类:

  • 等待阻塞:执行wait(),需要notify()/notifyAll()唤醒
  • 同步阻塞:等待拿到锁
  • 其他阻塞:执行sleep(),join(),或者发出I/O请求。都会进入阻塞

三.创建线程的几种方式?  

创建线程:

  • 创建一个Thread对象。new Thread().start;
  • 使用线程池 Executors.newFixedThreadPool(10); //创建线程池

定义线程做的事

  • 继承Thread类,重写run()
    • 需要创建一个子类
  • 实现Runnable接口,重写run()
    • 打破单继承的局限,可以在实现接口的时候继承自己的父类。
    • 可以使用lambda代替 ()->{}
  • 实现Callable接口,重写call()
    • 有返回值,有异常
    • 需要用一个过度类FutureTask,可以使用该类的get()获取返回值 

四.sleep,wait,yield,join的区别

sleep(),wait()的区别?

  • 所属的类不同:sleep来自Thread类,wait来自Object类
  • 有没有释放锁(释放资源)
    • sleep:不释放       wait:释放,进入等待池中(主要就是为了线程的通讯)
  • 使用的范围不同
    • sleep:任何地方    wait:必须使用在同步代码块/同步方法中
  • 是否有异常
    • sleep:有,需要捕获   wait:没有

补充:解释上面出现的名词

  • 锁池:需要竞争同步锁的线程都先放在锁池中,锁一旦释放,锁池中的线程开始抢锁
  • 等待池:当线程执行wait(),就会进入等待池中。执行notify()/notifyAll()就会将等待池中的线程放到锁池中(也就是唤醒)

yield和join

  • yield():线程让步
    • 暂停当前正在执行的线程对象,并执行其它线程。不进入阻塞
    • 当前线程交出cpu权限,让cpu执行其他线程(但是CPU可能重新分配时,再次执行该线程)
  • join():线程插入
    • 在线程a中调用线程b的join(),此时线程a进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态。

五.其他一些小问题

怎么理解线程安全问题?

  • 多个线程操作共享数据时,就会产生线程安全问题
  • 造成这个问题的本质就是堆空间是线程共享的

并发,并行,串行的区别?

  • 串行:执行完一个程序再执行下一个程序
  • 并行:多个事情,在一个时间点内发生。经常是对于多核cpu
  • 并发:多个事情,在一个时间段内发生。在这个时间段中cpu快速切换,感觉像一起执行
  • 并发编程的本质:充分利用CUP的资源

守护线程?

java中两种线程:守护线程(后台线程)    非守护线程(用户线程)

  • 守护线程是专门给所有的用户线程(非守护线程)提供服务的线程,不是专门给一个线程提供服务
  • gc垃圾回收线程就是典型的守护线程,当JVM中没有任何的用户线程执行,守护线程就会自动的断开
  • 使用守护线程中产生的线程也是守护线程
  • 不要把I/O,file操作交给守护线程,因为它随时可能中断(没有用户线程执行的时候)
  • 对于线程池Executors,就算你把它设置为守护线程,也会变为非守护线程
  • 使用thread.setDaemon(true);//将线程设置为守护线程

线程终止的几种方式?

  1. 正常运行结束
  2. 使用退出标志退出线程(将run()的所有内容放在while(flag)中)
  3. Interrupt()方法结束线程 while (!isInterrupted()){..Thread.sleep().}     推荐
    • Interrupt():如果线程处于阻塞状态,终止阻塞。抛出异常。然后在异常处理中break;
  4. stop()方法结束线程                                                                             不推荐
    • 强制终止线程,释放该线程的所有的锁。这样做就会导致锁释放,造成线程不安全。

线程是否越多越好?  不一定,线程多了上下文切换就多了

  • 对于计算的程序,线程数等于cpu核数最好
  • 对于i/o程序,线程数等于i/o任务数最好

 

寄语:把努力当成你的一种习惯,而不是一时热血

Tags: