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。此时两个线程都处于运行状态。所以才会出现最开始的那种运行结果。
实例二
线程类
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()方法 |
---|---|
使当前线程进入被阻塞的状态 | 将当前线程转入暂停执行的状态 |
即使没有其它等待运行的线程,当前线程也会等待指定的时间 | 如果没有其它等待执行的线程,当前线程会马上恢复执行 |
其它等待执行的线程的机会是均等的 | 会优先执行优先级相同或更高的线程 |