package com.lipeng; public class LoopDemo { /** * 线程A循环10次,然后线程B循环100次,然后A再循环10次,然后B再循环100次。如此循环50次。 * lipeng * 2015-4-10 * @param args */ public static void main(String[] args) { MyTask task=new MyTask(); RunA runA=new RunA(task); RunB runB=new RunB(task); new Thread(runA,"A").start(); //每个线程的start方法只能运行一次,但Run方法在不同的线程中可以运行多次。 new Thread(runB,"B").start(); } }
class RunA implements Runnable { private MyTask task; public RunA(MyTask task) { this.task=task; } @Override public void run() { try { for(int i=0;i<50;i++) { task.A(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
class RunB implements Runnable { private MyTask task; public RunB(MyTask task) { this.task=task; } @Override public void run() { try { for(int i=0;i<50;i++) { task.B(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
class MyTask { private boolean aGo=true;//切换开关,当true时A执行,false时B执行,执行完后切换条件 public synchronized void A()throws Exception{ while(!aGo) //为何不用if??? { //A 不能运行,等待 this.wait(); } for(int i=0;i<10;i++) { System.out.println("AAAAA--------------"+i); } //运行完之后,将aGo切换为FALSE,让B运行 aGo=false; this.notify();//唤醒一个正在等待的线程 } public synchronized void B()throws Exception{ while(aGo) { //B 不能运行,等待 this.wait(); } for(int i=0;i<100;i++) { System.out.println("B--------------"+i); } //运行完之后,将aGo切换为true,让A运行 aGo=true; this.notify();//唤醒一个正在等待的线程 } }
说明:
1. 如果有大于两个多线程在执行,最好用notifyAll,为什么?
例如,如果本例中多起几个线程,如果此时有A1,B1线程在wait,某个A线程执行完,将aGo置为false,并唤醒正在等待锁的其中一个线程,A1或B1,如果此时正好A1线程抢到了CPU,则A1运行,判断方法A1进入wait状态,而B1由于没有被唤醒,之后继续等待,那么到最后,A1和B1都处于wait状态,造成了死锁。
而如果改为notifyAll的话,A1和B1都被唤醒,抢到锁的线程先执行,如果A1抢到的话,继续等待,然后B1继续执行,因为此时aGo=false,所以B1执行,将aGo=true,A1继续执行完毕。
结论:只要A和B启动的线程的个数不同,就可能造成死锁的情况。
2.
判断aGo的地方为什么要使用while,if不行吗?在wait方法说明中,也推荐使用while,因为在某些特定的情况下,线程有可能被假唤醒,使用while会循环检测更稳妥。在本例中,A和B应该是交替运行的,但是如果多启动几个线程,如果有A1线程在等待(wait)状态,而A2线程执行完毕,aGo设置为false,唤醒正在等待的线程(可能是A也可能是B),如果是A被唤醒的话,如果用了if而不是while,那么A执行,这样A就连续执行了两遍,不符合我们的设计要求,但如果换用while的话,即使A被唤醒,他会再次判断aGo的值,发现是false,则继续等待。直到B线程将其唤醒。
时间: 2024-10-09 21:59:30