线程的由来
进程的开销比较大,cpu切换很耗时间,一个进程中也需要多个任务同时进行,例如一个浏览器可以打开多个页面进行浏览操作,一个页面又可以通过异步渲染来提升用户体验度
线程的就是最细力度的cpu运行单位,为了提高运行效率和减少资源占用
线程创建的几种方式
1.继承thread类,java类只能继承一个类
2.实现runnable接口,底层也是实现的Thread类, java类可以多实现,因此多用这种方式
3.实现callable/future,带返回值的线程
4.线程池创建
线程的六种状态
1.NEW 新建
2.Running 运行状态
3.wait 等待
4.timeWait 超时等待
5.blocked 锁阻塞
6.TERMINATED 终止
线程的启动方法
是start而不是run,run方法大家都知道,普通的方法,运行完就结束
这里思考一下线程的特性有哪些
1.每个线程的运行都是cpu切换到后才会运行
2.线程启动后不会去阻塞调用它的线程,也就是说他是异步执行的
很明显run方法做不到,那么start方法做了什么呢
通过jvm创建了一个线程,而jvm是通过不同的操作系统底层去创建,创建完后,等待cpu去运行它
cpu运行后会回调已经实现的run方法
线程的终止
首先这里要先入一个观点:线程结束一定是run方法运行结束
线程终止:指的仅仅是方法,一种表示
那么现在让我们了解线程终止相关的3个方法:
1.interrupt:修改线程终止状态,修改为true
2.interrupted:获取线程终止状态,并复位为false
3.isInterrupt:获取线程终止状态
通过上面3个方法我们了解到线程有一个终止状态,默认为false,这个是系统底层定义的
那么为什么需要线程终止方法呢?
当线程处于阻塞状态时,无法响应我们,我们怎么做才能让线程唤醒呢,通过interrupt方法
这里大家可能会觉得等到sleep,wait,join完成不就行了嘛,关键点在于我现在不相等
既然提到了这个就必须提一个事情:任何阻塞状态的线程调用阻塞方法时必定抛出一个只能捕获的interruptException,这个异常被捕获后,也会复位终止状态
为什么要复位
前提,复位时线程已经被唤醒,可以正常处理事务,加入当你处理任务时,别人又要你终止怎么办,此时你已经中断状态为true,那么别人调用interrupt方法,不会修改状态,无法感知到有人给你中断了,就相当于是死循环,而复位就代表你可以在处理上一次的中断后,再次接受到中断请求,从而完成这次中断就如同while(interrupt)一样,不复位就是死循环,永远也执行不了别的任务
线程的几个常用方法
1.park:阻塞,可以传入超时时间,不传就是一直阻塞
2.unPark:唤醒,可以指定线程
3.wait:阻塞,底层调用的park方法
4.notify:随机唤醒处于wait的线程,底层调用的UNpark
5.notifyAll:唤醒全部wait线程
6.sleep:带超时的阻塞
7.join:阻塞,但它是阻塞调用方