0 代码案例:
package thread;
/**
*
* @author zm
* 执行结果:
第 0 次执行B
第 1 次执行A
第 1 次执行B
第 2 次执行A
第 2 次执行B
第 3 次执行A
第 3 次执行B
第 4 次执行A
第 4 次执行B
第 5 次执行A
第 5 次执行B
第 6 次执行A
第 6 次执行B
第 7 次执行A
第 7 次执行B
第 8 次执行A
第 8 次执行B
第 9 次执行A
第 9 次执行B
*
* 须知:
* 1 高内聚 将业务方法封装到业务类上 在业务方法上设置锁,这样调用的线程只要使用同一个业务对象,就可以实现业务方法的互斥
* 2 多线程之间通讯的前提仍旧是业务方法上的锁是同一个,使用关键词 notify() wait() 实现多线程同一锁下的等待效果
*/
public class CommunicateThread {
// A 执行一次 B 执行一次 一共执行20次
public static void main(String[] args) {
final Out out = new Out(); // out对象就是同一个门栓
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0; i<10; i++){
out.printA(i);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0; i<10; i++){
out.printB(i);
}
}
}).start();
}
}
class Out { // 业务方法里面仅需要有业务,不要带线程的任何东西, 注意方法需要互斥时 需要同一个门栓,也只有使用同一个门栓才能在此线程用完当前门栓后唤醒别的要使用门栓的线程的功能
public boolean flag = true;
public synchronized void printA(int i){
while(!flag){// 当flag = false时,线程执行此业务方法时等待
try {
this.wait();// 门栓等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("第 " + i + " 次执行A"); // 否则直接执行业务方法
flag = false; // 更改标志位
this.notify(); // 用完这个门栓了 通知同样在等待使用这个门栓的线程使用此门栓 注意体会this的用法
}
public synchronized void printB(int j){
while(flag) {// 当flag = true时, 线程执行此业务方法时等待
try {
this.wait();// 门栓等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("第 " + j + " 次执行B");
flag = true; // 更改标志位
this.notify(); //
}
}
1 脑图: