线程休眠:sleep

public static void sleep(long millis)throws InterruptedException
设置休眠的毫秒数,一到时间自动唤醒
public static void sleep(long millis,int nanos)throws InterruptedException
设置休眠的毫秒数和纳秒数,一到时间自动唤醒

线程强制执行:join

Thread类中的join()方法原理

  • 一般是用在main方法中,用于占用主线程。
  • 副线程必须先start再join才有效
  • join方法的本质就是用调用方线程给主线程main上锁直到该线程结束才释放
  • 遇到join时,主线程立即被占用,不会存在安全问题,因为本质就是同步机制
  • 如果同时存在两个以上的副线程,并且同时对main用join上锁,那么main线程的恢复执行以最后一次锁结束为准,不同线程之间不受影响,因为他们占用的都是main线程而没有彼此占用
class J1Thread extends Thread{
    @Override
    public void run() {
        for(int i=1;i<100;i++){
            System.out.println(Thread.currentThread().getName()+"\t11111111111");
            try {
                sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class J2Thread extends Thread{
    public void run() {
        for(int i=1;i<100;i++){
            System.out.println(Thread.currentThread().getName()+"\t22222222222");
            try {
                sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
public class JoinTest {
    public static void main(String[] args) throws InterruptedException {
        J1Thread j1 = new J1Thread();//创建线程对象
        J2Thread j2 = new J2Thread();//创建线程对象
        for(int i =1;i<100;i++) {//主线程main真正开始的地方
            Thread.sleep(10);
            System.out.println(Thread.currentThread().getName()+"\t主线程开始"+i);
        }//执行完for循环体才会轮得到后面j1的开始
        j1.start();//先创建j1的线程
        j1.join();//用j1给主线程main上锁,知道j1结束才释放
        for(int i =1;i<100;i++) {//主线程main继续
            Thread.sleep(10);
            System.out.println(Thread.currentThread().getName()+"\t主线程中途"+i);
        }//执行完for循环体才会轮得到后面j2的开始
        j2.start();
        for(int i =1;i<100;i++) {
            Thread.sleep(10);
            System.out.println(Thread.currentThread().getName()+"\t主线程结束"+i);
            if(i==90)//for循环体途中用join上锁
       j2.join();//然后j2占用main线程,把剩余部分执行完毕
        }
    }
}

Java第二天唤醒 java sleep唤醒_主线程

Java第二天唤醒 java sleep唤醒_主线程_02

 线程让步:yield()

本质:多线程并发执行是多个线程交替执行,对于某一个线程并不会执行一下就马上释放,而是会持续一个随机的很短的时间。因此通过yield方法可以强制让正在占用资源的线程让出资源,让包括自己在内的所有线程去争夺资源。因此

  • yield没有join那么强硬,join是直接上锁,yield只是放弃资源让大家重新争夺
  • yield也没有sleep那么稳定,yield有极小概率没有任何让步效果,而sleep则稳定延迟
  • 执行次数足够多时yield也能明显看到让步效果
  • 同样的yield无论写多少个都一样,而同样的sleep写10个就有10倍的延迟效果
class MyThread1 implements Runnable{
    public void run() {
        for (int i = 100; i < 200; i++) {
           System.out.println("11111111礼让");
               yield();
        }
    }
}

class YouThread1 implements Runnable{
    public void run() {
        for (int i = 100; i < 200; i++) {
            System.out.println("22222222");

        }
    }
}
public class YiledTest {
    public static void main(String[] args) {
        MyThread1 M1 = new MyThread1();
        YouThread1 Y1 = new YouThread1();
        Thread T1 = new Thread(M1);
        Thread T2 = new Thread(Y1);

        T1.start();
        T2.start();
    }
}

Java第二天唤醒 java sleep唤醒_System_03

这一礼让基本把自己让没了