Java四个线程常用函数超全使用详解

网友投稿 324 2022-08-18


Java四个线程常用函数超全使用详解

目录前言1. wait()2. join()3. sleep()4. yield()5. 总结5.1 wait和join的区别5.2 wait和sleep的区别

前言

之前没怎么关注到这两个的区别以及源码探讨

后面被某个公司面试问到了,开始查漏补缺

1. wait()

使当前线程等待,直到它被唤醒,通常是通过被通知或被中断,或者直到经过一定的实时时间。

本身属于一个Object 类,查看源代码也可知:public class Object {

查看其源码可知,一共有三个重载的方法,详情源代码如下:

//第一个重载函数

public final void wait() throws InterruptedException {

wait(0L);

}

//第二个重载函数

public final native void wait(long timeoutMillis) throws InterruptedException;

//第三个重载函数

public final void wait(long timeoutMillis, int nanos) throws InterruptedException {

if (timeoutMillis < 0) {

throw new IllegalArgumentException("timeoutMillis value is negative");

}

if (nanos < 0 || nanos > 999999) {

throw new IllegalArgumentException(

"nanosecond timeout value out of range");

}

if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {

timeoutMillis++;

}

wait(timeoutMillis);

}

具体实战调用代码如下:

如果执行到了wait函数,在这4秒内,会释放锁,并且暂停线程。如果这四秒内配合notify()可以唤醒并且得到锁,如果没有唤醒,等待其他来竞争。4秒结束后,会默认自动释放锁

当前线程在 Thread.wait()等待过程中,如果Thread结束了,是可以自动唤醒的而且自动释放锁

@Override

public void run() {

synchronized (a) {

a.wait(4000);

}

}

2. join()

join是Thread类的方法

查看其源码,具体源码如下,三个重载的方法

//第一个重载函数

public final synchronized void join(final long millis)

throws InterruptedException {

if (millis > 0) {

if (isAlive()) {

final long startTime = System.nanoTime();

long delay = millis;

do {

wait(delay);

} while (isAlive() && (delay = millis -

TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0);

}

} else if (millis == 0) {

while (isAlive()) {

http:// wait(0);

}

} else {

throw new IllegalArgumentException("timeout value is negative");

}

}

//第二个重载函数

/*等待该线程死亡的时间最多为毫秒加纳秒。 如果两个参数都为0,则意味着永远等待。

这个实现使用了This的循环。 等待电话以this.isAlive为条件。 当一个线程终止this。

调用notifyAll方法。 建议应用程序不要使用wait、notify或notifyAll on Thread实例。 */

public final synchronized void join(long millis, int nanos)

throws InterruptedException {

if (millis < 0) {

throw new IllegalArgumentException("timeout value is negative");

}

if (nanos < 0 || nanos > 999999) {

throw new IllegalArgumentException(

"nanosecond timeout value out of range");

}

if (nanos > 0 && millis < Long.MAX_VALUE) {

millis++;

}

join(millis);

}

//第三个重载函数

/*等待线程死亡。

此方法的调用与调用的行为完全相同

InterruptedException—如果任何线程中断了当前线程。 当抛出此异常时,当前线程的中断状态将被清除。 */

public final void join() throws InterruptedException {

join(0);

}

主要的时间参数逻辑如下:

小于0,抛出异常等于0,join(A),判断A是否存在,存在才执行操作。该线程执行wait(0)等待,等待A线程执行完后才可结束大于0,同上,只不过执行的是wait(long millis),等待时间结束后才可继续执行操作

3. sleep()

对比上一个wait函数

sleep(long mills):让出CPU资源,但是不会释放锁资源。wait():让出CPU资源和锁资源。

查看sleep函数的源码,一共有两个重载函数

都是Thread类的函数

/*根据系统计时器和调度器的精度和准确性,

使当前执行的线程在指定的毫秒数内处于睡眠状态(暂时停止执行)。

线程不会失去任何监视器的所有权。*/

public static native void sleep(long millis) throws InterruptedException;

/*导致当前执行的线程在指定的毫秒数加上指定的纳秒数

(取决于系统计时器和调度器的精度和准确性)内休眠(暂时停止执行)。

线程不会失去任何监视器的所有权。 */

public static void sleep(long millis, int nanos)

throws InterruptedException {

if (millis < 0) {

throw new IllegalArgumentException("timeout value is negative");

}

if (nanos < 0 || nanos > 999999) {

throw new IllegalArgumentException(

"nanosecond timeout value out of range");

}

if (nanos > 0 && millis < Long.MAX_VALUE) {

millis++;

}

sleep(millis);

}

4. yield()

查看yield()函数的源码,一个重载函数

都是Thread类的函数

向调度器暗示当前线程愿意放弃当前对处理器的使用。 调度器可以忽略这个提示。

Yield是一种启发式尝试,旨在改善线程之间的相对进程,否则会过度使用CPU。 它的使用应该与详细的分析和基准测试相结合,以确保它实际上具有预期的效果。

使用这种方法很少是合适的。 它可能用于调试或测试目的,在这些目的中,它可能有助于由于竞争条件而重新生成错误。 在设计并发控制构造(如java.util.concurrent.locks包中的构造)时,它可能也很有用。

public static native void yield();

总的来说,yield函数的功能主要是:

让出CPU调度,暂停线程,但不能由用户指定时间

只能让同优先级有执行机会

5. 总结

wait 暂停该线程,让出cpu,释放锁。(Object类)

join暂停该线程,执行该线程之后才能回到自身的线程运行。(Thread类)

sleep 暂停该线程,让出cpu,不释放锁。(Thread类)

yield 暂停该线程,但是不能由用户制定,只能让同优先级有执行机会。(Thread类)

5.1 wait和join的区别

看完以上的源码以及逻辑代码,再讲讲两者的异同

总的来说

wait函数:让当前线程进入等待状态,wait()会与notify()和notifyAll()方法一起使用。notify为唤醒函数join函数:等待这个线程结束才能执行自已的线程。它的主要起同步作用,使线程之间的执行从“并行”变成“串行”。线程A中调用了线程B的join()方法时,线程

执行过程发生改变:线程A,必须等待线程B执行完毕后,才可以继续执行下去

共同点:

暂停当前的线程都可以通过中断唤醒

不同点在于:

区别waitjoin类Object类Thread类目的线程间通信排序,让其串行通过同步必须要synchronized可以不用synchronized

5.2 wait和sleep的区别

wait():让出CPU资源和锁资源。

sleep(long mills):让出CPU资源,但是不会释放锁资源。

看区别,主要是看CPU的运行机制:

它们的区别主要考虑两点:1.cpu是否继续执行、2.锁是否释放掉。

归根到底:

wait,notify,notifyall 都是Object对象的方法,是一起使用的,用于锁机制,所以会释放锁

而sleep是Thread类,跟锁没关系,不会释放锁

但是两者都会让出cpu资源

以上就是Java四个线程常用函数超全使用详解的详细内容,更多关于Java线程函数的资料请关注我们其它相关文章!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot加载配置文件的实现方式总结
下一篇:Java 详细分析四个经典链表面试题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~