• 技术文章 >Java >java教程

    Java常用的四个线程函数有哪些?

    WBOYWBOY2023-04-26 14:01:07转载23

    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()) {
                    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);
     }

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

    3. sleep()

    对比上一个wait函数

    查看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的区别

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

    总的来说

    执行过程发生改变:线程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常用的四个线程函数有哪些?的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:亿速云,如有侵犯,请联系admin@php.cn删除
    专题推荐:Java
    上一篇:如何使用Java实现员工信息管理系统功能? 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • Java函数式编程实例分析• Go Java算法之解码方法实例代码分析• Java的编译时错误和运行时错误问题怎么解决• 怎么用Java语言打开文件和写入文件• Java Cloneable接口的深拷贝与浅拷贝方法
    1/1

    PHP中文网