线程交替输出,那么肯定是要利用线程之间的同步协调。离不开Object对象中的wait()与Notify()方法。
思路:
- 创建两个线程A,B,一个全局变量i记数,一个全局变量obj协调两个线程。
- A输出一个数字,i++,obj.wait(),等待B执行。
- B输出一个数字,i++,叫醒A(obj.notify()),再obj.wait()。
- A输出一个数字,i++,叫醒B(obj.notify()),再obj.wait()。
… 重复步骤34 直到 i == 100。
思路逻辑大家应该都可以理解,需要注意的点为:
对象obj应该创建为全局变量。否则不能起到沟通协调的作用。
我们需要使用synchronized关键字为obj上锁,以此协调两个线程。synchronized在此处的用法为同步方法块:
锁的是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。
obj即为上述的对象。作为一个“工具人”在此处只起到一个“中介”的作用。
具体同步实现逻辑为:
- 当一个线程(假设为A)访问到synchronized代码块时,对象obj即被锁住,(也可以理解为此代码块被锁住),A线程获得锁。线程B运行到这里后便不能再访问此代码块。
- 当A执行完obj.wait()方法后,A释放锁,此时线程B获得锁。
- 当B进入代码块后,正常输出逻辑。
- 当B执行obj.notify()后,会唤醒A,但是不会立即释放锁,而是等到执行完wait()方法后才会释放锁。
逻辑如上所述,如果obj属于具体某一个线程,那么另一个线程便不能访问到obj,起不到协调的作用,所以obj一定要为公共属性(被static修饰的)。
代码如下:
package com;
public class Thread_test extends Thread{
static int i = 0;
// static Object obj = new Object();
static Object obj = new Object(); //使用obj作为通信,务必使用static,
public void run() {
super.run();
while (i <= 10) {
synchronized (obj) { //使用obj作为通信
try {
System.out.println("name:" + Thread.currentThread().getName());
System.out.println(i++);
obj.notify();
obj.wait();
} catch (Exception e) {
}
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread_test();
Thread t2 = new Thread_test();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}