线程中常见的方法
start()
启动一个新的线程,在新的线程中运行run()方法中的代码
start方法只是让线程进入就绪状态,不是马上运行。需要等待CPU的时间片分给它
一个线程的 start 方法只能调用一次,如果多次调用会抛出IllegalThreadStateException
run()
新线程启动后会调用的方法,如果在构造 Thread 对象时传递了 Runnable,线程启动后会调用 Runnable 中的 run 方法,否则默认不执行任何操作
如果同时传递 Runnable 和重写 run 方法,那么会执行的当然是重写的 run 方法
join()
等待某个线程结束
如下代码:
主线程直接获取a的值,得到的是0
如果我们想要读取到t1修改a的值,那么就需要使用join()
join内部是用wait方法实现的
join如果不带时间,那就是一直等。如果带了时间,那就是如果时间到了还没线程还没结束,那么就继续了,不等了
yield()
调用 yield 方法会调度执行其他同优先级的线程。如果这时没有其他同优先级的线程,那么不能保证让当前线程暂停
yield 的作用只相当于提示,并不保证一定有效果,具体的实现依赖于操作系统的任务调度器
这个方法的主要作用在于测试和调试
sleep()
这个方法很熟悉了,使线程暂停一段时间,如果持有锁,那么 sleep 时也不会释放锁
wait()
必须持有锁才能调用此方法,否则会抛出IllegalMonitorStateException
。作用在于当一个线程获取锁之后,发现当前不满足执行条件,空等又浪费资源,所以使用 wait 方法释放锁,自己进入 Monito r中 waitset 中等待被 notify 和 notifyall 唤醒。释放锁之后,其他线程抢到锁成为 owner ,没抢到的继续阻塞
wait 方法并不是 Thread 类中的方法,而是 Object 的方法
为什么这些操作线程的方法要定义在 Object 类中呢?
简单说:因为 synchronized 中的这把锁可以是任意对象,所以任意对象都可以调用 wait() 和 notify() ;所以 wait 和 notify 属于 Object 。
专业说:因为这些方法在操作同步线程时,都必须要标识它们操作线程的锁,只有同一个锁上的被等待线程,可以被同一个锁上的 notify 唤醒,不可以对不同锁中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法是定义在Object类中
sleep 和 wait 的区别
- sleep 是 Thread 方法,而 wait 是 Object 的方法
- sleep 不需要强制和 synchronized 配合使用,但 wait 需要和 synchronized 一起用,也就是上面说的一定要获取到锁
- sleep 如果获取到了锁,不会释放,但是wait会释放锁
interrupt()
打断线程
如果被打断线程正在 sleep,wait,join 会导致被打断的线程抛出InterruptedException,并清除打断标记
如果打断正在运行的线程,则会设置打断标记
isInterrupted:判断是否被打断,不会清除打断标记
interrupted:判断是否被打断,会清除打断标记