三、线程的调度(补)join()与sleep()

join()实例:

实例一

线程类:

public class MyThread implements Runnable{
    
    public String value1;
    public String value2;

    public void run() {
        value1 = "value1  has  a  zhi";
        value2 = "value2  has  a  zhi";
    }

}

测试类:

public class Demo {
    public static void main(String[] args) {
        MyThread demo = new MyThread();
        Thread demo2 = new Thread(demo);
        demo2.start();
        System.out.println(demo.value1);
        System.out.println(demo.value2);
    }
}

输出结果为:

null
value2  has  a  zhi

在run()方法中,已经对value1和value2赋值了,而返回的是null。出现这种情况的原因是在主线程中国调用了start()方法后就立刻输出了value1和value2的值,而run()方法可能还没有执行到为value1和value2赋值的语句,要避免这种情况的发生,需要等到run()方法执行完才执行输出value1和value2的代码,可以使用join()方法看来解决这个问题。在demo2.start();后面加上demo2.join();
此时的输出结果为:

value1  has  a  zhi
value2  has  a  zhi

结果分析:
这个程序的运行情况如下:执行main函数,当执行到demo2.start()的时候,开启了第二个线程,但是此时main函数还是会继续向下执行,不会等demo2。此时两个线程都处于运行状态。所以才会出现最开始的那种运行结果。


image.png

实例二

线程类

public class MyThread  implements Runnable {
    public int value1;
    public int value2;

    public void run() {
        value1 = 1;
        value2 = 2;
    }
    
}
public class MyThread2 implements Runnable {
    public int value3;
    public int value4;
    public void run() {
        value3 = 1;
        value4 = 2; 
    }
    
}

测试类:

public class Test {
    public static void main(String[] args) {
        MyThread demo1 = new MyThread();
        MyThread2 demo2 = new MyThread2();
        Thread test1 = new Thread(demo1);
        Thread test2 = new Thread(demo2);
        test1.start();
        System.out.println(demo1.value1);
        System.out.println(demo1.value2);
        test2.start();
        System.out.println(demo2.value3);
        System.out.println(demo2.value4);   
    }

}

运行结果:

0
2
0
0

当测试类这样写的时候:

public class Test {
    public static void main(String[] args) {
        MyThread demo1 = new MyThread();
        MyThread2 demo2 = new MyThread2();
        Thread test1 = new Thread(demo1);
        Thread test2 = new Thread(demo2);
        test1.start();
        test2.start();
        System.out.println(demo1.value1);
        System.out.println(demo1.value2);
        System.out.println(demo2.value3);
        System.out.println(demo2.value4);       
    }

}

运行结果为:

1
2
1
2

分析:不知道,问老师吧。

sleep()实例

实例一

sleep()方法会让当前线程睡眠(停止执行)million毫秒,线程由运行中的状态进入不可运行状态,睡眠时间过后线程会再次进入可运行状态。
实例:让主函数睡眠一段时间,即停止主函数的执行一段时间。

package cn.kgc.p3;

public class Wait {
    public static void waitBySec(long s) {
        for (int i = 0; i < s; i++) {
            System.out.println((i+1) + "秒");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

测试类:

public class Demo {

    public static void main(String[] args) {
        Wait.waitBySec(5);
        System.out.println(1);
    }

}

结果:

1秒
2秒
3秒
4秒
5秒
1

或者也可以直接在main函数中这么写:

public class Demo {
    public static void main(String[] args) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(1);
    }
}

Thread类的sleep是个静态方法,可以在main方法中直接调用。

实例二

线程类:

public class MyThread implements Runnable {
    public int value1;
    public int value2;

    public void run() {
        value1 = 1;
        value2 = 2;
    }
}
public class MyThread2 implements Runnable {
    public int value3;
    public int value4;
    public void run() {
        value3 = 1;
        value4 = 2;
        
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        MyThread demo1 = new MyThread();
        MyThread2 demo2 = new MyThread2();
        Thread test1 = new Thread(demo1);
        Thread test2 = new Thread(demo2);
        test1.start();
        test2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(demo1.value1);
        System.out.println(demo1.value2);
        System.out.println(demo2.value3);
        System.out.println(demo2.value4);   
    }

}

结果如下:

1
2
1
2

分析:sleep方法时让当前线程阻塞一段时间,在这个程序中,线程一和线程二都已经启动了,此时我让main函数阻塞额几秒,此时足以让线程一和二都执行结束,所以main函数再运行时输出的属性都已经被赋值了。
思考:在上面的示例中,当我的主函数这样写时:

public class Test {
    public static void main(String[] args) {
        MyThread demo1 = new MyThread();
        MyThread2 demo2 = new MyThread2();
        Thread test1 = new Thread(demo1);
        Thread test2 = new Thread(demo2);
        test1.start();
        test2.start();
        try {
            test1.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println(demo1.value1);
        System.out.println(demo1.value2);
        System.out.println(demo2.value3);
        System.out.println(demo2.value4);

        

    }

}

结果如下:

1
2
1
2

结果:在main函数中,我是让test1阻塞了一段时间,但是这段时间内main函数并没有运行,相反也阻塞了同样的时间,为什么?同时输出的结果也是两个线程全都赋值之后的结果,为什么?

yield()方法:暂停线程

实例:
第一个线程类:

public class FirstThread extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("第一个线程的第" + (i+1) + "次输出。");
            Thread.yield();
        } 
    }
}

第二个线程类:

public class SecondThread extends Thread{
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("第二个线程的第" + (i+1) + "次输出。");
            Thread.yield();
        }
    }
}

主函数:

public class Demo {
    public static void main(String[] args) {
        FirstThread ft = new FirstThread();
        SecondThread st = new SecondThread();
        ft.start();
        st.start();
    }
}

运行结果:

第一个线程的第1次输出。
第二个线程的第1次输出。
第一个线程的第2次输出。
第一个线程的第3次输出。
第一个线程的第4次输出。
第一个线程的第5次输出。
第二个线程的第2次输出。
第二个线程的第3次输出。
第二个线程的第4次输出。
第二个线程的第5次输出。

在以上实例中,调用了yield()方法后,当前线程并不是转入了被阻塞状态,它可以与其它等待执行的线程竞争CPU资源,如果此时它又抢占到了CPU资源,就会出现连续运行几次的情况。

疑问如下:你yield方法既然是让当前线程暂停执行,允许其他线程执行,那在这个例子中,两个线程都在运行,当第一个线程暂停的时候,第二个线程会执行啊,我认为记过应该是两个线程交替执行,为什么实际上会是上面的结果?

sleep()方法 与yield()方法对比

sleep()方法 yield()方法
使当前线程进入被阻塞的状态 将当前线程转入暂停执行的状态
即使没有其它等待运行的线程,当前线程也会等待指定的时间 如果没有其它等待执行的线程,当前线程会马上恢复执行
其它等待执行的线程的机会是均等的 会优先执行优先级相同或更高的线程

你可能感兴趣的:(三、线程的调度(补)join()与sleep())