线程中sleep()、wait()、join()、yield()方法的使用

本文详细介绍了Java多线程中的四个关键方法:sleep()使得线程休眠但不释放锁;wait()则让线程等待并释放对象锁,可通过notify()或notifyAll()唤醒;join()让当前线程等待指定线程执行完再继续;yield()则是让当前线程暂停,让相同优先级的线程有机会执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
sleep()方法使当前线程放弃CPU使用权,但是不释放已抢占对象的锁,当前线程阻塞。其他线程可以抢占cpu使用权,但无法抢占对象的锁。sleep 方法允许较低优先级的线程获得运行机会
sleep()方法是Thread类的静态方法
Thread.sleep(2000);线程休眠2秒
thread.interrupt();可以终止线程的阻塞,并抛出InterruptedException异常,捕获异常后,线程可以继续运行
 */

/*
wait()方法使当前线程放弃CPU使用权,并且释放已抢占对象的锁,当前线程阻塞。其他线程可以抢占cpu使用权,并且抢占对象的锁。
o.notify();可以唤醒1个被o.wait();阻塞的线程
o.notifyAll();可以唤醒所有被o.wait();阻塞的线程
o.wait();线程等待
o.wait(2000);线程等待2秒
thread.interrupt();可以终止线程的阻塞,并抛出InterruptedException异常,捕获异常后,线程可以继续运行
 */

/*
join()方法,thread2.join()使当前线程放弃CPU使用权,并且释放已抢占对象的锁,等待thread2线程执行完毕后,当前线程继续运行。
thread.interrupt();可以终止线程的阻塞,并抛出InterruptedException异常,捕获异常后,线程可以继续运行
 */

/*
yield()方法,Thread.yield()使当前线程放弃CPU使用权,然后当前线程和与当前线程优先级相同的线程竞争抢占cpu使用权,如果没有和当前线程优先级相同的线程,则当前线程继续获得cpu使用权,继续执行。

yield()使当前线程放弃CPU使用权,但是不释放已抢占对象的锁,所以yield()方法要在synchronized代码块外使用才有效果。

在线程数量小于cpu核心数的情况下,不存在cpu使用权的竞争,只有在线程数量多于cpu核心数的情况下才存在CPU使用权的竞争,此时yield()方法才会有效果。
 */

wait():

有3个线程抢占o对象的锁,并分别对aa、bb、cc进行++操作,但是aa、bb、cc两两相差不能超过2

public class Main3 {

    static Object o = new Object();
    static Integer aa = 0;
    static Integer bb = 0;
    static Integer cc = 0;
    
    public static void main(String[] args) {
        
        Runnable runnableA = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程正在运行");
                synchronized (o) {
                    while (aa < 4) {
                        if (aa-bb >= 2 || aa-cc >= 2) {
                            try {
                                System.out.println(name + " 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程");
                                o.notifyAll();
                                o.wait();
                            } catch (InterruptedException e) {
                                System.out.println(name + " 线程阻塞被终止,进入就绪状态");
                            }
                        } else {
                            aa++;
                            for (int i = 1; i <= 2100000000; i++) {
                                if (i == 2100000000) {
                                    System.out.println(name+" 线程完成了 "+aa+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
                                }
                            }
                        }
                    }
                    //退出之前唤醒其他等待的线程
                    o.notifyAll();
                }
                System.out.println(name + " 线程完成任务");
            }
        };

        Runnable runnableB = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程正在运行");
                synchronized (o) {
                    while (bb < 4) {
                        if (bb-aa >= 2 || bb-cc >= 2) {
                            try {
                                System.out.println(name + " 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程");
                                o.notifyAll();
                                o.wait();
                            } catch (InterruptedException e) {
                                System.out.println(name + " 线程阻塞被终止,进入就绪状态");
                            }
                        } else {
                            bb++;
                            for (int i = 1; i <= 2100000000; i++) {
                                if (i == 2100000000) {
                                    System.out.println(name+" 线程完成了 "+bb+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
                                }
                            }
                        }
                    }
                    //退出之前唤醒其他等待的线程
                    o.notifyAll();
                }
                System.out.println(name + " 线程完成任务");
            }
        };

        Runnable runnableC = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程正在运行");
                synchronized (o) {
                    while (cc < 4) {
                        if (cc-bb >= 2 || cc-aa >= 2) {
                            try {
                                System.out.println(name + " 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程");
                                o.notifyAll();
                                o.wait();
                            } catch (InterruptedException e) {
                                System.out.println(name + " 线程阻塞被终止,进入就绪状态");
                            }
                        } else {
                            cc++;
                            for (int i = 1; i <= 2100000000; i++) {
                                if (i == 2100000000) {
                                    System.out.println(name+" 线程完成了 "+cc+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
                                }
                            }
                        }
                    }
                    //退出之前唤醒其他等待的线程
                    o.notifyAll();
                }
                System.out.println(name + " 线程完成任务");
            }
        };

        Thread thread1 = new Thread(runnableA);
        Thread thread2 = new Thread(runnableB);
        Thread thread3 = new Thread(runnableC);
        thread1.start();
        thread2.start();
        thread3.start();
        
    }

运行结果:wait()方法使当前线程放弃CPU使用权,并且释放已抢占对象的锁,其他线程可以抢占cpu使用权,并签章对象的锁。

Thread-0 线程正在运行
Thread-2 线程正在运行
Thread-1 线程正在运行
Thread-0 线程完成了 1 次伟大的循环,aa=1,bb=0,cc=0
Thread-0 线程完成了 2 次伟大的循环,aa=2,bb=0,cc=0
Thread-0 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程
Thread-1 线程完成了 1 次伟大的循环,aa=2,bb=1,cc=0
Thread-1 线程完成了 2 次伟大的循环,aa=2,bb=2,cc=0
Thread-1 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程
Thread-2 线程完成了 1 次伟大的循环,aa=2,bb=2,cc=1
Thread-2 线程完成了 2 次伟大的循环,aa=2,bb=2,cc=2
Thread-2 线程完成了 3 次伟大的循环,aa=2,bb=2,cc=3
Thread-2 线程完成了 4 次伟大的循环,aa=2,bb=2,cc=4
Thread-2 线程完成任务
Thread-1 线程完成了 3 次伟大的循环,aa=2,bb=3,cc=4
Thread-1 线程完成了 4 次伟大的循环,aa=2,bb=4,cc=4
Thread-1 线程完成任务
Thread-0 线程完成了 3 次伟大的循环,aa=3,bb=4,cc=4
Thread-0 线程完成了 4 次伟大的循环,aa=4,bb=4,cc=4
Thread-0 线程完成任务

sleep():

有3个线程抢占o对象的锁,并分别对aa、bb、cc进行++操作,但是aa、bb、cc两两相差不能超过2

public class Main4 {

    static Object o = new Object();
    static Integer aa = 0;
    static Integer bb = 0;
    static Integer cc = 0;
    
    public static void main(String[] args) {
        
        Runnable runnableA = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程正在运行");
                synchronized (o) {
                    while (aa < 4) {
                        if (aa-bb >= 2 || aa-cc >= 2) {
                            try {
                                System.out.println(name + " 线程放弃CPU使用权,但是不放弃对象的锁,当前线程阻塞,其他线程无法获得对象的锁");
                                Thread.sleep(4000);
                            } catch (InterruptedException e) {
                                System.out.println(name + " 线程阻塞被终止,进入就绪状态");
                            }
                        } else {
                            aa++;
                            for (int i = 1; i <= 2100000000; i++) {
                                if (i == 2100000000) {
                                    System.out.println(name+" 线程完成了 "+aa+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
                                }
                            }
                        }
                    }
                }
                System.out.println(name + " 线程完成任务");
            }
        };

        Runnable runnableB = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程正在运行");
                synchronized (o) {
                    while (bb < 4) {
                        if (bb-aa >= 2 || bb-cc >= 2) {
                            try {
                                System.out.println(name + " 线程放弃CPU使用权,但是不放弃对象的锁,当前线程阻塞,其他线程无法获得对象的锁");
                                Thread.sleep(4000);
                            } catch (InterruptedException e) {
                                System.out.println(name + " 线程阻塞被终止,进入就绪状态");
                            }
                        } else {
                            bb++;
                            for (int i = 1; i <= 2100000000; i++) {
                                if (i == 2100000000) {
                                    System.out.println(name+" 线程完成了 "+bb+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
                                }
                            }
                        }
                    }
                }
                System.out.println(name + " 线程完成任务");
            }
        };

        Runnable runnableC = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程正在运行");
                synchronized (o) {
                    while (cc < 4) {
                        if (cc-bb >= 2 || cc-aa >= 2) {
                            try {
                                System.out.println(name + " 线程放弃CPU使用权,但是不放弃对象的锁,当前线程阻塞,其他线程无法获得对象的锁");
                                Thread.sleep(4000);
                            } catch (InterruptedException e) {
                                System.out.println(name + " 线程阻塞被终止,进入就绪状态");
                            }
                        } else {
                            cc++;
                            for (int i = 1; i <= 2100000000; i++) {
                                if (i == 2100000000) {
                                    System.out.println(name+" 线程完成了 "+cc+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
                                }
                            }
                        }
                    }
                }
                System.out.println(name + " 线程完成任务");
            }
        };

        Thread thread1 = new Thread(runnableA);
        Thread thread2 = new Thread(runnableB);
        Thread thread3 = new Thread(runnableC);
        thread1.start();
        thread2.start();
        thread3.start();
        
    }

运行结果:由于sleep()不会使线程放弃对象的锁,所以获得锁的线程将无限循环。

Thread-1 线程正在运行
Thread-0 线程正在运行
Thread-2 线程正在运行
Thread-1 线程完成了 1 次伟大的循环,aa=0,bb=1,cc=0
Thread-1 线程完成了 2 次伟大的循环,aa=0,bb=2,cc=0
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
。。。。。。

join():

主线程和子线程分别执行10次伟大的循环,但是主线程比较懒,想等子线程执行完毕后再执行,子线程执行两次后感觉太累,想找个作伴的,于是把主线程喊醒了,两个线程一起执行。

    public static void main(String[] args) {
        Thread mainThread = Thread.currentThread();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程 开始 执行");
                int j = 1;
                for (; j <= 2; j++) {
                    for (int i = 0; i < 2100000000; i++) {
                        if (i == 0) {
                            System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
                        }
                    }
                }
                System.out.println("太累了,主线程你快起来,抓紧时间干活。");
                mainThread.interrupt();
                for (; j <= 10; j++) {
                    for (int i = 0; i < 2100000000; i++) {
                        if (i == 0) {
                            System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
                        }
                    }
                }
                System.out.println(name + " 线程执行完毕");
            }
        };
        Thread thread1 = new Thread(runnable, "thread1");
        thread1.start();
        try {
            System.out.println("我是主线程,我先休息会,等thread1 线程执行完我再执行。");
            thread1.join();
        } catch (InterruptedException e) {
            System.out.println("主线程还没休息够就被终止休息了,继续干活。");
        }
        for (int k = 1; k <= 10; k++) {
            for (int i = 0; i < 2100000000; i++) {
                if (i == 0) {
                    System.out.println("主线程完成 " + k + " 次伟大的循环");
                }
            }
        }
        System.out.println("主线程执行完毕");
    }

运行结果:

我是主线程,我先休息会,等thread1 线程执行完我再执行。
thread1 线程 开始 执行
thread1 线程完成 1 次伟大的循环
thread1 线程完成 2 次伟大的循环
太累了,主线程你快起来,抓紧时间干活。
主线程还没休息够就被终止休息了,继续干活。
thread1 线程完成 3 次伟大的循环
主线程完成 1 次伟大的循环
主线程完成 2 次伟大的循环
主线程完成 3 次伟大的循环
thread1 线程完成 4 次伟大的循环
主线程完成 4 次伟大的循环
thread1 线程完成 5 次伟大的循环
主线程完成 5 次伟大的循环
thread1 线程完成 6 次伟大的循环
主线程完成 6 次伟大的循环
thread1 线程完成 7 次伟大的循环
thread1 线程完成 8 次伟大的循环
主线程完成 7 次伟大的循环
主线程完成 8 次伟大的循环
thread1 线程完成 9 次伟大的循环
主线程完成 9 次伟大的循环
thread1 线程完成 10 次伟大的循环
主线程完成 10 次伟大的循环
thread1 线程执行完毕
主线程执行完毕

yield():

    public static void main(String[] args) {
        Object o = new Object();
        CountDownLatch co = new CountDownLatch(1);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name + " 线程 开始 执行");
                try {
                    co.await();
                } catch (InterruptedException e) {
                    
                }
                int j = 1;
                synchronized (o) {
                    for (; j <= 2; j++) {
                        for (int i = 0; i < 2100000000; i++) {
                            if (i == 0) {
                                System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
                            }
                        }
                    }
                    System.out.println(name + " 线程让步");
                    // 线程让步,但不释放锁,所以线程还会获得cup执行权继续执行。
                    Thread.yield();
                    for (; j <= 6; j++) {
                        for (int i = 0; i < 2100000000; i++) {
                            if (i == 0) {
                                System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
                            }
                        }
                    }
                }
                System.out.println(name + " 线程让步");
                // 线程让步,此时没有锁,然后当前线程会和同等优先级的线程共同竞争CPU使用权。
                // 在线程数量小于cpu核心数的情况下,不存在cpu使用权的竞争,在线程数量多余cpu核心数的情况下才存在CPU使用权的竞争。
                Thread.yield();
                synchronized (o) {
                    for (; j <= 10; j++) {
                        for (int i = 0; i < 2100000000; i++) {
                            if (i == 0) {
                                System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
                            }
                        }
                    }
                }
            }
        };
        Thread thread1 = new Thread(runnable, "thread1");
        Thread thread2 = new Thread(runnable, "thread2");
        Thread thread3 = new Thread(runnable, "thread3");
        Thread thread4 = new Thread(runnable, "thread4");
        // 优先级高只是获得cpu使用权的几率高而已,并不代表优先级高的线程要先执行。
        thread1.setPriority(Thread.MIN_PRIORITY);
        thread2.setPriority(Thread.NORM_PRIORITY);
        thread3.setPriority(Thread.NORM_PRIORITY);
        thread4.setPriority(Thread.MAX_PRIORITY);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            
        }
        co.countDown();
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值