进程与线程
进程是操作系统资源分配的基本单位,每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;在操作系统中能同时运行多个进程(程序);系统在运行的时候会为每个进程分配不同的内存空间;没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的。
线程是任务调度和执行的基本单位,线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行);对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
线程的生命周期、状态
新建状态(New):新创建了一个线程对象。使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法,该线程就进入就绪状态。该状态的线程位于可运行线程池中,就绪状态的线程处于就绪队列中,变得可运行,等待获取CPU的使用权,要等待JVM里线程调度器的调度。
运行状态(Running):如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
线程优先级
每一个Java线程都有一个优先级,Java线程的优先级用整数表示,线程的优先级别不会决定哪个线程先启动,只能建议JVM哪个线程先执行,高优先级的线程比低优先级的线程有更高的几率得到执行,分布在Thread.MIN_PRIORITY和Thread.MAX_PRIORITY之间(分别为1和10)
默认情况下,新创建的线程都拥有和创建它的线程相同的优先级。main方法所关联的初始化线程拥有一个默认的优先级,这个优先级是Thread.NORM_PRIORITY (5),线程的当前优先级可以通过getPriority方法获得,线程的优先级可以通过setPriority方法来动态的修改,一个线程的最高优先级由其所在的线程组限定
线程的调度
1、线程睡眠(sleep):Thread.sleep(long millis)方法,使线程转到阻塞状态,等待线程睡眠设定时间后进入就绪状态,不释放锁。millis参数设定睡眠的时间,以毫秒为单位sleep()平台移植性好。
2、线程让步(yield):Thread.yield() 方法,暂停当前正在执行的线程对象,使线程转到就绪状态,不释放锁,把执行机会让给相同或者更高优先级的线程。
3、线程加入(join):Thread.join()方法,在当前线程中调用另一个线程的join()方法,则使当前线程转入阻塞状态,直到另一个线程运行结束,当前线程再由阻塞转为就绪状态。join()方法底层用wait()实现,所以会使当前线程释放锁。
4、线程等待(wait):Object.wait()方法,导致当前的线程等待,进入阻塞状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法,使该线程进入就绪状态,释放锁。
5、线程唤醒(notify):Object.notify()方法和Object.notifyAll()方法,唤醒在此对象监视器上等待的单个线程或所有线程,使线程从阻塞状态变成就绪状态。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。