一个多线程分别打印abc的问题

welen 2014-03-06 09:09:22
运行这段代码,前面可以打印两三次abc,然后就卡住了,初步估计应该都进入wait了,但是不明白为什么,求指导
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 = 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();
}
}else{
System.out.println("c");
obj.num = 0;
obj.notifyAll();
}
}
}
}
}

class Locker {
int num = 0;
}
...全文
236 6 打赏 收藏 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
陆荃 2014-03-06
  • 打赏
  • 举报
回复
问题分析: 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; } 浅薄之见,还望指教。
nmyangym 2014-03-06
  • 打赏
  • 举报
回复
我的粗浅看法: 楼主这样的逻辑,用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;
}
tony4geek 2014-03-06
  • 打赏
  • 举报
回复
你理解下

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;
	}
welen 2014-03-06
  • 打赏
  • 举报
回复
引用 1 楼 rui888 的回复:
one two three 的调度顺序问题。
怎么改,按我理解,每次三个线程中总有一个执行了else的代码块,然后通过notifyall唤醒所有等待的,下一次应该就只有num指定的线程可以执行else的代码了。。这样每次都可以有一个else可以得到执行。。事实不是这样,所以不理解了,能说清楚吗
tony4geek 2014-03-06
  • 打赏
  • 举报
回复
one two three 的调度顺序问题。
faker-_- 2014-03-06
  • 打赏
  • 举报
回复
测试了一下,每个线程都去掉else就可以了。因为假如A线程在sleep被唤醒时,它只会进行执行if下面的程序,而if下面没有唤醒其他线程的代码,这样所有的代码都是出于sleep状态了。
内容概要:本文围绕通过短时倒谱(Cepstrogram)计算进行时-倒频分析的研究,提出了一种基于Matlab的信号处理方法,旨在从复杂信号中提取时变的倒频域特征,尤其适用于具有非线性反馈的LTI系统识别。文中系统阐述了短时倒谱的理论基础、计算流程与实现机制,并结合Simulink与Matlab代码实现了多个典型应用案例,涵盖非线性系统辨识、路径损耗建模、信号去噪与增强等,充分展示了该方法在系统建模与信号分析中的强大能力。研究不仅提供了完整的算法实现方案,还深入探讨了其在科研与工程实践中的广泛应用前景。; 适合人群:具备扎实的信号处理理论基础与Matlab编程能力,从事自动化、通信工程、电子工程、控制科学等领域的高校研究生、科研人员及工程技术人员。; 使用场景及目标:①实现对具有非线性反馈的LTI系统的精确建模与参数辨识,提升系统识别的准确性与鲁棒性;②在强噪声背景下进行有效的信号特征提取与时-倒频域分析,恢复信号的有效成分;③作为高级信号处理的教学与科研平台,帮助深入理解倒谱分析的物理意义及其在现代工程中的实际应用。; 阅读建议:建议读者在学习过程中紧密结合文中提供的Matlab代码与Simulink模型进行动手实践,通过调整参数、修改输入信号等方式观察分析结果的变化,以加深对算法机理的理解;同时可访问作者提供的网盘资源与完整代码包,系统性地掌握相关技术的优化与拓展方法。

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧