多线程相关知识

《Java并发编程的艺术》总结

  操作系统调度的最小单元是线程,也叫轻量级进程(LightWeight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。

为什么要使用多线程

  • 更多的处理器核心

线程是大多数操作系统调度的基本单元,一个程序作为一个进程来运行,程序运行中会创建多个线程,而一个线程在某一时刻只能运行在一个处理器核心上

  • 更快的响应时间

  • 更好的编程模型

线程优先级

Java线程中,通过整型成员变量 priority 来控制优先级,优先级的范围为1~10 。在线程构建的时候,通过 setPriority() 方法来修改优先级,默认为5,优先级高的线程分配时间片的数量要高于优先级低的线程。

线程优先级不能作为程序正确性的依赖,因为操作系统可以完全不用理会Java线程对于优先级的设定。

线程状态

  • new:初始状态,线程被构建,但还没有调用start()方法
  • runnable:运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称为:“运行中”
  • blocked:阻塞状态,表示线程阻塞于锁
  • waiting:等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或者中断)
  • time_waiting:超时等待状态,该状态不同于waiting,它可以在指定的时间自行返回
  • terminated:终止状态,表示当前线程已经执行完毕

多线程

线程中start与run的区别
run():只是调用了一个普通方法,并没有启动另一个线程,程序会按照顺序去执行代码
start():重新开启一个线程,不必等待其他线程运行完毕,只要得到cup就会执行该线程

等待/通知机制

  • notify():通知一个在对象上等待的线程,使其从 wait() 方法返回,而返回的前提是该线程获取到了对象的锁
  • notifyAll():通知所有等待在该对象上的线程
  • wait():调用该方法的线程进入waiting状态,只有等待另外的线程通知或者被中断才会返回,需要注意,调用wait() 方法后,会释放对象锁
  • wait(long):超时等待一段时间,这里的参数时间为毫秒,也就是等待长达n毫秒,如果没有通知就超时返回
  • wait(long, int):对于超市时间更细粒度的控制,可以达到纳秒

sleep与wait的区别
sleep是Thread的方法,wait是Object的方法。sleep不会导致锁行为的改变

Daemon线程

Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这意味着,当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出。可以通过调用Thread.setDaemon(true)将线程设置为Daemon线程。

ThreadLocal的使用

ThreadLocal,即线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构。这个结构被附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。

线程池技术

目的
  • 降低资源消耗
  • 提高响应速度
  • 提高线程的可管理性
运行步骤
  • 线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。
  • 线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
  • 线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

ThreadPoolExecutor执行示意图

使用
new ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler);

new ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory);
  • corePoolSize(线程池的基本大小)
  • runnableTaskQueue(任务队列)
    • ArrayBlockingQueue
    • LinkedBlockingQueue
    • SynchronousQueue
    • SynchronousQueue
  • maximumPoolSize(线程池最大数量)
  • ThreadFactory:用于设置创建线程的工厂
  • RejectedExecutionHandler(饱和策略)
    • AbortPolicy:直接抛出异常
    • CallerRunsPolicy:只用调用者所在线程来运行任务
    • DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
    • DiscardPolicy:不处理,丢弃掉
  • keepAliveTime(线程活动保持时间)
  • TimeUnit(线程活动保持时间的单位)

补充知识:进程调度算法

  • 先来先服务(FCFS)
  • 最短作业优先(SJF)
  • 基于优先权的调度算法(FPPS)
  • 时间片轮转(RR)
  • 多级队列调度(Multilevel feedback queue)
0

发表评论

This site uses Akismet to reduce spam. Learn how your comment data is processed.