run方法和start方法
start() 方法
启动一个新线程。在新的线程中运行run方法中的代码
start方法只是让线程进入就绪,里边代码不一定立刻运行(CPU的时间片还没分给他)。每个线程对象的start方法只能调用一次,如果调用了多次会出现IllegalThreadStateException
run()
新线程启动后会调用的方法
如果在构造Thread对象时传递了Runnable参数,则线程启动后会调用Runnable中的run方法,否则默认不执行任何操作。但可以创建Thread的子类对象,来覆盖默认行为。
执行上述代码之后,我们发现最后执行的还是main线程,即是在主线程中调用的run
但是当我们使用t1.start()的时候,通过输出我们发现,是t1线程在执行run方法,与主线程并行执行。
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
sleep()方法
- 调用sleep会让当前线程从Running进入TimedWaiting状态
- 其他线程可以使用interrupt方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException
- 睡眠结束后的线程未必会立刻得到执行
- 建议用TimeUnit的sleep代替Thread的sleep来获得更好的可读性
此处TimeUnit仅仅做了数值的转换,底层调用的还是sleep方法,仅仅是为了更好的可读性
yield()方法
- 调用yield会让当前线程从Running进入Runable就绪状态,然后调度执行其他线程
- 具体的实现依赖于操作系统的任务调度器
sleep方法和yield方法一个是程序进入TimedWaiting 状态,一个是让程序进入Runable状态,Runable状态还是有机会被执行的,时间片还是可能分配给他的,但是TimedWaiting不会。
线程优先级
- 线程优先级会提示调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略他
- 如果cpu比较忙,那么优先级高的线程会获得更多的时间片,但cpu闲的时候,优先级几乎没作用
线程优先级1 - 10 ,优先级由低到高,默认为5
join()方法
等待线程结束
等待t1线程运行结束后,继续运行
join() --> 线程的同步
以调用角度来讲,如果
- 需要等待结果返回,才能继续运行的就是同步
- 不需要等待结果返回,就能继续运行的就是异步
join(long n) --> 限时同步
等待线程运行结束,最多等待n毫秒
join的原理
如果是没有参数,调用的就是等待0秒,而millis为0,就是调用的wait(0),即一直等待
如果大于0,使用的是保护性暂停模式
interrupt()方法
如果打断sleep,wait,join线程,即处于阻塞状态的线程,会清空打断标记,即标记为false,同时会抛出异常
当打断处于正常运行状态的线程时,不会中断该线程,只是将其终端标志位置为true,不影响线程的运行。只是告诉你,我要打断你,由被打断线程决定,我是否要中断。
打断park线程,同时会将打断标志置为true ,但是只要标志状态为true,就进入不了park状态了,再想进入park状态,需要清空标志,比如调用interrupted方法
isInterrupted()和interrupted()
都是判断当前是否被打断,区别在于interrupted()会清除打断标记
不推荐的方法
这些方法已过时,容易破坏同步代码块,造成线程死锁
stop() --> 停止线程运行 ==替代== 两阶段终止模式
suspend() --> 挂起(暂停)线程运行 ==替代== wait()
resume() --> 恢复线程运行 ==替代== notify()