Java线程休眠方法sleep、线程让步yield和join方法
线程休眠(sleep方法)
线程休眠:让线程暂缓执行,等到预计时间之后再恢复执行。
线程休眠会交出cpu,让cpu去执行其他任务,但是不会释放锁。
比如:当前线程sleep休眠了,但是如果此线程在休眠前持有某个对象的锁,那就算它休眠了其他线程也不能获取到这个对象的锁。
注意:调用sleep结束后线程会重新回到就绪状态,只需要等待获取cpu执行就可以。
方法:
public static native void sleep(long millis) throws InterruptedException
休眠的时间是以毫秒为单位
使用:
class MyThread implements Runnable{
@Override
public void run() {
for(int i = 0; i < 5; i++){
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" i=" + i);
}
}
}
public class Test{
public static void main(String[] args){
MyThread myThread = new MyThread();
new Thread(myThread).start();
new Thread(myThread).start();
new Thread(myThread).start();
}
}
线程让步(yield()方法)
yield():暂停当前正在执行的线程对象,并执行其他线程。
线程让步会交出cpu权限,让cpu去执行其他的线程。和sleep方法类似,同样不会释放锁,但是yield不能控制具体交出cpu的时间,并且,yield方法只能让拥有相同优先级的线程有获取cpu执行的机会。
注意:调用yield结束后线程会重新回到就绪状态,只需要等待获取cpu执行就可以。
使用:
class MyThread implements Runnable{
@Override
public void run() {
for(int i = 0; i < 5; i++){
Thread.yield();
System.out.println(Thread.currentThread().getName()+" i=" + i);
}
}
}
public class Test{
public static void main(String[] args){
MyThread myThread = new MyThread();
new Thread(myThread).start();
new Thread(myThread).start();
new Thread(myThread).start();
}
}
等待其他线程终止-join()方法
意思就是说如果在主线程中调用这个方法时会让主线程休眠,让调用该方法的线程run方法先执行完毕后再开始执行主线程。
join放发实际上是对wait方法的封装。
我们来看join的源码
public final void join() throws InterruptedException {
join(0);
}
我们可以看到join方法实际上是调用了join(0);
join(long millis)方法如下:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从上面我们可以提取出join(0)调用的部分代码;如下:
if (millis == 0) {
while (isAlive()) {//判断当前线程是否为Running状态
wait(0);
}
从上面可以看出如果调用此方法的线程是正在运行的线程,那么就会调用wait(0)方法,
关于wait()的源码:
public final native void wait(long timeout) throws InterruptedException;
wait(long timeout)是一个本地方法,调用本机的原生系统函数,当Thread类被加载到JVM中的时候,它就会调用注册相应的本地方法。
wait(0)就是让其他线程一直在等待,当此线程终止时,会调用线程自身的notifyAll()方法,唤醒所有等待在该线程对象上的线程。
使用:
public class Test{
public static void main(String[] args) throws InterruptedException {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
});
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t1.start();
t3.start();
t2.start();
}
}
运行结果:
t1
t2
t3
当t2比t3start时间迟的时候,出现下面结果
public class Test{
public static void main(String[] args) throws InterruptedException {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
});
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t1.start();
t3.start();
Thread.sleep(2000);//让主线程休眠2秒,那么在t3调用join时t2还不是运行状态
t2.start();
}
}
运行结果如下:
t1
t3
t2
这就是因为join(0)中调用了
if (millis == 0) {
while (isAlive()) {//判断当前线程是否为Running状态
wait(0);
}
因为t2不处于运行状态所以不会执行wait(0),所以t3就不会等待,直接运行下一条语句。