多线程
一、实现方式
Thread、runable、callable、线程池
四大线程池:newCachedThreadPool、newFixedThreadPool、newScheduledThreadPool、newSingleThreadExecutor.
newCachedThreadPool:有Cached的是创建根据需要常见线程的线程池,适合短期异步任务,一个线程执行完任务,可重复利用,并且会移除那些60秒钟未被使用的线程。这个线程池可以节省资源。发现没有可用线程,才会创建线程。
newFixedThreadPool:这个就是创建出固定的线程来完成任务,如果所有线程都处于活动状态,那么将新来的任务,放入队列中等待。线程池中的线程除非被显式的关闭,否则将一直存在。
newScheduledThreadPool:可在创建时,传入时间参数,让线程在给定延迟后运行命令或者定期执行。
newSingleThreadExecutor:这个线程池只有一个线程,只有在线程死后,重新启动一个线程来替代原来的线程继续执行下去。
二、线程声明状态
新建、就绪、运行、阻塞、死亡五种状态。
线程启动之后,不可能一直霸占CPU资源,CPU是在多条线程之间切换的,于是线程状态也会多次在运行、阻塞之间切换。
1、新建状态:
new一个线程之后,该线程处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值。
2、就绪状态:
线程对象调用了Start方法之后,该线程处于就绪状态。java虚拟机为其创建方法调用栈和程序计数器。等待调度运行
3、运行状态:
就绪状态的线程获得了CPU,开始执行run方法的线程执行体,该线程处于运行状态。
4、阻塞状态:
阻塞状态是指线程因为某种原因让出了线程的使用权。也即让出了CPU timeslice(时间片),暂时停止运行。阻塞状态有三种:
4.1、等待阻塞:运行中的线程执行wait方法,JVM会把该线程放入等待队列中
4.2 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,JVM会把该线程放入锁池中。(这种状态,首先要理解,锁的概念,一段代码被加上了锁,线程是怎么进去的,就是线程获得了这个锁,其他线程来了,一看这个锁被占了,只能等着,有点美女和一群恶霸的感觉,只有一个恶霸走了,才能有另一个恶霸接手。~~)
4.3 其他阻塞:线程执行sleep、join、I/O请求时,JVM会把该线程置为阻塞状态。当sleep状态超时、join等待线程终止或者超时、或者I/O处理完毕,线程进入运行状态。
5、线程死亡:
正常结束:
run或者call方法执行完成,线程正常结束
线程抛异常也会结束
直接调用stop方法结束,容易死锁,不推荐使用。
总结:一个线程刚刚被创建出来,也就是new出来,这个时候是新建状态,JVM会在堆内存中为其分配内存,并初始化其值。代码跑起来后,执行到start方法后,JVM为线程创建虚拟机栈和程序计数器,等待调度。运行到run方法,也就是在执行线程的执行体,该线程进入运行状态,CPU被抢,线程进入阻塞状态。代码运行完,没有抛异常,线程死亡。