线程的几个状态
- 新建状态:new Thread()
- 就绪状态:等待CPU调度
- 运行状态:CPU开始执行run方法
- 阻塞状态:sleep或者wait方法使线程休眠
- 死亡状态:run方法执行完毕或者调用stop方法强行中 断线程(不建议使用,会造成数据的丢失和线程的持续运行)
线程的创建
线程的创建有三个方法,其中前两个方法较为常见
- 方法一:继承Thread类
- 方法二:实现Runable接口
以上两个方法都是通过重写父类中的run方法来实现线程任务的建立,再通过调用start方法来执行线程任务 - 方法三:实现callable接口
此方法是重写父类中的call方法实现线程任务的建立,在通过start方法执行线程任务
线程的相关方法
- start():1.启动当前线程2.调用线程中的run方法
- run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
- currentThread():静态方法,返回执行当前代码的线程
- getName():获取当前线程的名字
- setName():设置当前线程的名字
- yield():主动释放当前线程的执行权
- join():在线程中插入执行另一个线程,该线程被阻塞,直到插入执行的线程完全执行完毕以后,该线程才继续执行下去
- stop():过时方法。当执行此方法时,强制结束当前线程。
- sleep(long millitime):线程休眠一段时间(会抛出异常)
- isAlive():判断当前线程是否存活
线程运行的方式
线程可分为安全线程和不安全线程,其中
线程池
可以提供多个线程同时存在,当有任务进入时会按照顺序开始依次执行任务,当全部有任务执行是,下一个任务会等待有空闲的线程存在时再进行执行
线程池为类:ExcutorService
线程池可分为缓存线程池,定长线程池,周期性定长线程池,单线程池四种
1.缓存线程池:ExcutorService service = Executors.newCachedThreadPool()
之后调用service 中的execute方法向先线程池中添加线程
2.定长线程池:ExcutorService service = Executors.newFixedThreadPool(参数1)
其中参数一为线程池的大小
之后调用service 中的execute方法向先线程池中添加线程
3.周期性定长线程池:ScheduledExcutorService service = Executors.newScheduledThreadPool(参数1)
其中参数一为线程池的大小
定时执行一次线程:调用方法schedule(参数一,参数二,参数三)
其中参数一为定时执行的任务,即线程任务,参数二为间隔时长数字,参数三为时长数字的单位,用TimeUnit的常量指定
周期性执行任务:调用方法scheduAtFixedRate(参数一,参数二,参数三,参数四)
参数一为执行的任务,参数二为延迟时长的数字(第一次执行在什么时间以后),参数三为周期时长数字(隔多久执行一次),参数四为时长数字单位
4.单线程线程池:ExcutorService service = Executors.newSingleThreadPool()
之后调用service 中的execute方法向先线程池中添加线程
线程安全
线程安全问题是指,多个线程对同一个共享数据进行操作时,线程没来得及更新共享数据,从而导致另外线程没得到最新的数据,从而产生线程安全问题。
解决线程的安全问题有三种方法:
方式一:同步代码块
使用同步监视器(锁)
Synchronized(同步监视器){
//需要被同步的代码
}
方式二:同步方法
使用同步方法,对方法进行synchronized关键字修饰
将同步代码块提取出来成为一个方法,用synchronized关键字修饰此方法。
对于runnable接口实现多线程,只需要将同步方法用synchronized修饰
而对于继承自Thread方式,需要将同步方法用static和synchronized修饰,因为对象不唯一(锁不唯一)
方法三:lock锁方法
在线程开始之前实例化锁ReentrantLock lock = new ReentrantLock()之后调用锁定方法lock()是实现对线程的锁定,结束同步也需要手动的实现(unlock())
线程的死锁
线程的死锁问题就是指所有线程都处于阻塞状态,无法继续
死锁的解决办法:
1.减少同步共享变量
2.采用专门的算法,多个线程之间规定先后执行的顺序,规避死锁问题
3.减少锁的嵌套,尽量不去线程中调用另一个线程
线程通信
通信方法
1.wait方法:一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
2.notify方法:一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程,就唤醒优先级高的线程
3.notifyAll方法:一旦执行此方法,就会唤醒所有被wait()的线程
使用前提:这三个方法均只能使用在同步代码块或者同步方法中。