解决方案 »

  1.   

    one two three 的调度顺序问题。
      

  2.   

    怎么改,按我理解,每次三个线程中总有一个执行了else的代码块,然后通过notifyall唤醒所有等待的,下一次应该就只有num指定的线程可以执行else的代码了。。这样每次都可以有一个else可以得到执行。。事实不是这样,所以不理解了,能说清楚吗
      

  3.   

    你理解下
    public class TestDemo {
     public static void main(String[] args) {
            final Locker p = new Locker();
            Task11 a = new Task11(p);
            Task21 b = new Task21(p);
            Task31 c = new Task31(p);
            Thread one = new Thread(a);
            one.start();
            Thread two = new Thread(b);
            two.start();
         //   Thread three = new Thread(c);
         //   three.start();
        }
    }
     
     
    class Task11 implements Runnable {
         
        private Locker obj;
        public Task11(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    if(obj.num != 0){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        System.out.println("a");
                        obj.num = 1;
                        obj.notifyAll();
                    }
                }
            }
        }
    }
    class Task21 implements Runnable {
         
        private Locker obj;
        public Task21(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    if(obj.num != 1){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        System.out.println("b");
                        obj.num = 0;
                        obj.notifyAll();
                    }
                }
            }
        }
    } class Task31 implements Runnable {
         
        private Locker obj;
        public Task31(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    if(obj.num != 2){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        System.out.println("c");
                        obj.num = 0;
                        obj.notifyAll();
                    }
                }
            }
        }
    }
     
    class Locker {
        int num = 0;
    }
      

  4.   

    我的粗浅看法:
    楼主这样的逻辑,用while 好一些。看下面的代码:public class TestDemo {
     
        public static void main(String[] args) {
            final Locker p = new Locker();
            Task11 a = new Task11(p);
            Task21 b = new Task21(p);
            Task31 c = new Task31(p);
            Thread one = new Thread(a);
            one.start();
            Thread two = new Thread(b);
            two.start();
            Thread three = new Thread(c);
            three.start();
        }
    }
     
     
    class Task11 implements Runnable {
         
        private Locker obj;
        public Task11(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    while(obj.num != 0){//if 改成while,只要num != 0, 肯定等待。
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //必须num == 0 , 才执行。
                    System.out.println("a");
                    obj.num = 1;
                    obj.notifyAll();
                }
            }
        }
    }
    class Task21 implements Runnable {
         
        private Locker obj;
        public Task21(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    while(obj.num != 1){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("b");
                    obj.num = 2;
                    obj.notifyAll();
                }
            }
        }
    }
    class Task31 implements Runnable {
         
        private Locker obj;
        public Task31(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    while(obj.num != 2){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("c");
                    obj.num = 0;
                    obj.notifyAll();
                }
            }
        }
    }
     
    class Locker {
        int num = 0;
    }
    如果不用while, 需要这样改:public class TestDemo {
     
        public static void main(String[] args) {
            final Locker p = new Locker();
            Task11 a = new Task11(p);
            Task21 b = new Task21(p);
            Task31 c = new Task31(p);
            Thread one = new Thread(a);
            one.start();
            Thread two = new Thread(b);
            two.start();
            Thread three = new Thread(c);
            three.start();
        }
    }
     
     
    class Task11 implements Runnable {
         
        private Locker obj;
        public Task11(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    if(obj.num != 0){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //唤醒时判断num值,是0,执行输出;否则,本次唤醒无意义,需要把i减一,继续循环。而用while 就比较好。楼主试一下。
                        if(obj.num == 0){
                         System.out.println("a");
                            obj.num = 1;
                            obj.notifyAll();
                        }
                        else {
                         i--;
                        }
                    }
                    else {
                     System.out.println("a");
                        obj.num = 1;
                        obj.notifyAll();
                    }
                }
            }
        }
    }
    class Task21 implements Runnable {
         
        private Locker obj;
        public Task21(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    if(obj.num != 1){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if(obj.num == 1){
                         System.out.println("b");
                            obj.num = 2;
                            obj.notifyAll();
                        }
                        else {
                         i--;
                        }
                    }
                    else {
                     System.out.println("b");
                        obj.num = 2;
                        obj.notifyAll();
                    }
                }
            }
        }
    }
    class Task31 implements Runnable {
         
        private Locker obj;
        public Task31(Locker p){
            this.obj = p;
        }
         
        @Override
        public void run() {
            for(int i = 0; i < 5; i++){
                synchronized (obj) {
                    if(obj.num != 2){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if(obj.num == 2){
                         System.out.println("c");
                            obj.num = 0;
                            obj.notifyAll();
                        }
                        else {
                         i--;
                        }
                    }
                    else {
                     System.out.println("c");
                        obj.num = 0;
                        obj.notifyAll();
                    }
                }
            }
        }
    }
     
    class Locker {
        int num = 0;
    }
      

  5.   

    问题分析:
    for循环可能会执行到wait分支,故不可能打印所有的5个a(或者b,c)。
    至于程序有时(占大比例)会停住,是因为比如task11已经跑完for循环,而此时task21,31均处于wait状态,没有地方触发notifyAll,所以会停住。解决方法:
    问题关键点在于for循环的5次肯定不能输出五次a,b,c。
    愚以为,作如下改动能实现楼主要求:
    public class TestDemo { public static void main(String[] args) {
    final Locker p = new Locker();
    Task11 a = new Task11(p);
    Task21 b = new Task21(p);
    Task31 c = new Task31(p);
    Thread one = new Thread(a, "Task11");
    one.start();
    Thread two = new Thread(b, "Task21");
    two.start();
    Thread three = new Thread(c, "Task31");
    three.start();
    }
    }class Task11 implements Runnable { private Locker obj; public Task11(Locker p) {
    this.obj = p;
    } @Override
    public void run() {
    int i = 0;
    while (true) {
    synchronized (obj) {
    if (obj.num != 0) {
    try {
    obj.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    } else {
    System.out.println("a");
    obj.num = 1;
    obj.notifyAll();
    if (4 == i++)
    break;
    }
    }
    }
    }
    }class Task21 implements Runnable { private Locker obj; public Task21(Locker p) {
    this.obj = p;
    } @Override
    public void run() {
    int i = 0;
    while (true) {
    synchronized (obj) {
    if (obj.num != 1) {
    try {
    obj.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    } else {
    System.out.println("b");
    obj.num = 2;
    obj.notifyAll();
    if (4 == i++)
    break;
    }
    }
    }
    }
    }class Task31 implements Runnable { private Locker obj; public Task31(Locker p) {
    this.obj = p;
    } @Override
    public void run() {
    int i = 0;
    while (true) {
    synchronized (obj) {
    if (obj.num != 2) {
    try {
    obj.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    } else {
    System.out.println("c");
    obj.num = 0;
    obj.notifyAll();
    if (4 == i++)
    break;
    }
    }
    }
    }
    }class Locker {
    int num = 0;
    }浅薄之见,还望指教。
      

  6.   

    测试了一下,每个线程都去掉else就可以了。因为假如A线程在sleep被唤醒时,它只会进行执行if下面的程序,而if下面没有唤醒其他线程的代码,这样所有的代码都是出于sleep状态了。