概念:sleep
会使当前线程睡眠指定时间(就是说当前线程暂停一段时间让给别的线程去运行,等到睡眠时间结束,线程自动复活),不释放锁
关于释放锁 / 不释放锁
:
sleep()是不释放锁的;也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象;因为当前线程仍然持有该对象的锁。
用法:
public class ThreadTest extends Thread {
@Override
public void run() {
System.out.println("我是重写后的run方法");
try {
sleep(2000);//ms单位
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是睡眠后被执行的");
}
public static void main(String[] args) {
ThreadTest t1=new ThreadTest();
// ThreadTest t2=new ThreadTest();
t1.start();
}
}
线程状态:调用sleep方法使得线程从运行态—>阻塞态
概念: yield
暂停当前正在执行的线程对象,让cpu去执行其他具有相同优先级的线程,不释放锁;
1.是让当前线程交出CPU权限,让CPU去执行其他具有相同优先级的的线程;
2.使得线程回到就绪态,以允许具有相同优先级的其他线程获得运行机会。
3.使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
总结: yield
方法只能让拥有优先级的线程获取CPU执行时间的机会,调用该方法不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行的时间。
线程状态:调用yield方法使得线程从运行态—>就绪态
用法: 同上
但是yield不能立刻交出CPU,会出现同一个线程一直执行的情况,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。
举例:
public class ThreadTest extends Thread {
public void run() {
System.out.println("In run");
yield();
System.out.println("Leaving run");
}
public static void main(String []argv) {
(new ThreadTest()).start();
}
}
//答案:程序运行可能输出先有In run后有Leaving run
我们去调用,想让线程去执行的方法
线程创建以后,并不会自动运行,需要我们手动的调用start
把线程的状置为为就绪状态;但不一定马上就被运行,得等到CPU分配时间片以后,才会运行。
线程状态:调用start()方法,创建—>就绪
cpu去调用,线程被真正 执行的方法
线程真正要执行的逻辑,当一个线程被分配到cpu资源,开始启动就会调用run方法执行
线程状态:就绪—>运行
概念:join方法,当前线程调用某线程.join()
时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁;
t1和t2两个线程,如果在t1线程里面调用了
t2.join()
,则t1线程会进行等待状态,t2运行结束以后,才会继续运行t1。这样可以保证线程的先后顺序。
线程状态:调用join()方法,线程从运行态—>阻塞态
注意:wait() 其实是Object类里面的方法,调用对象的wait方法导致线程放弃CPU的执行权,同时也放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool)
概念:wait()
使当前线程阻塞,使当前线程回到线程池中等待,释放锁,当被其他线程使用notify,notifyAll 唤醒时进入就绪状态;(前提是必须先获得锁)
一般配合synchronized来使用,即:在 synchronized 同步代码块里使用 wait()、notify() / notifyAll() 方法,
wait
方法由当前所有的local对象里面调用,this.wait(),必须被try catch包围,保证即使异常中断也可以使wait等待的线程唤醒。执行了wait方法,需要被别的线程通过同一个对象的notify方法唤醒。
线程状态:调用wait()方法,线程从运行态—>阻塞态
总结:wait notify notifyAll
都必须在持有有锁的代码中
概念:
obj.notify:随机唤醒对象obj的某个wait线程,使被唤醒的线程进入就绪状态。
obj.notifyAll:唤醒对象obj的所有wait线程,使被唤醒的线程进入就绪状态。
总结:
notify/notifyAll()
的执行只是唤醒沉睡的线程,而不会立即释放锁,锁的释放要看代码块的具体执行情况。