Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-多线程和同步_Java_Multithreading_Synchronization_Wait_Notify - Fatal编程技术网

Java-多线程和同步

Java-多线程和同步,java,multithreading,synchronization,wait,notify,Java,Multithreading,Synchronization,Wait,Notify,我有两个非常相似的程序,每个程序都试图运行两个线程OddThread和EvenThread,并试图按顺序打印奇数和偶数。第一个有效,第二个挂起。有人能指出第二个程序中的错误吗 第一个有效的方法是: public class ThreadTest { public static void main(String[] args) { System.out.println("Odd Even test"); NumHolder objNumHolder = new NumHolder

我有两个非常相似的程序,每个程序都试图运行两个线程OddThread和EvenThread,并试图按顺序打印奇数和偶数。第一个有效,第二个挂起。有人能指出第二个程序中的错误吗

第一个有效的方法是:

public class ThreadTest {

public static void main(String[] args) {
    System.out.println("Odd Even test");
    NumHolder objNumHolder = new NumHolder();
    Odd o1 = new Odd(objNumHolder, "Odd Number Thread");
    Even e1 = new Even(objNumHolder, "Even Number Thread");
    o1.start();
    e1.start();
}
}

class NumHolder {
private int intCurrNum;
private boolean isEven = false;

public synchronized void printOddNumber(String tname) {
    while (isEven == true){
        try {
            wait();
        }catch (InterruptedException e) {
        }
    }
    isEven = true;
    System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
    intCurrNum += 1;
    notifyAll();
}

public synchronized void printEvenNumber(String tname) {
    while (isEven == false) {
        try {
            wait();
        } catch (InterruptedException e) {
        }
    }
    isEven = false;
    System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
    intCurrNum += 1;
    notifyAll();
}
}

class Even extends Thread {
private NumHolder objNumHolder;

public Even(NumHolder p_objNumHolder, String name) {
    super(name);
    objNumHolder=p_objNumHolder;
}

public void run() {
    for (int i = 0; i < 10; i++) {
        objNumHolder.printEvenNumber(getName());
    }
}
}
class Odd extends Thread {
private NumHolder objNumHolder;

public Odd(NumHolder p_objNumHolder,String name) {
    super(name);
    objNumHolder = p_objNumHolder;
}

public void run() {
    for (int i = 0; i < 10; i++) {
        objNumHolder.printOddNumber(getName());
    }
}
}
公共类线程测试{
公共静态void main(字符串[]args){
System.out.println(“奇偶测试”);
NumHolder objNumHolder=新NumHolder();
奇数o1=新奇数(objNumHolder,“奇数螺纹”);
偶数e1=新偶数(objNumHolder,“偶数螺纹”);
o1.start();
e1.start();
}
}
类NumHolder{
私有int intCurrNum;
私有布尔值isEven=false;
公共同步的void printOddNumber(字符串tname){
while(isEven==true){
试一试{
等待();
}捕捉(中断异常e){
}
}
isEven=真;
System.out.println(“线程名称=“+tname+”==Number=“+intCurrNum”);
intCurrNum+=1;
notifyAll();
}
公共同步的void printEvenNumber(字符串tname){
while(isEven==false){
试一试{
等待();
}捕捉(中断异常e){
}
}
isEven=假;
System.out.println(“线程名称=“+tname+”==Number=“+intCurrNum”);
intCurrNum+=1;
notifyAll();
}
}
类甚至扩展了线程{
私人NumHolder objNumHolder;
公共偶数(NumHolder p_objNumHolder,字符串名称){
超级(姓名);
objNumHolder=p_objNumHolder;
}
公开募捐{
对于(int i=0;i<10;i++){
printEvenNumber(getName());
}
}
}
类奇数扩展线程{
私人NumHolder objNumHolder;
公共奇数(NumHolder p_objNumHolder,字符串名称){
超级(姓名);
objNumHolder=p_objNumHolder;
}
公开募捐{
对于(int i=0;i<10;i++){
printOddNumber(getName());
}
}
}
挂起的第二个代码:

class PrintClass {
int intCurrNum;
private boolean isEven = false;

synchronized void printOdd(){
    while(isEven){
        try{
            wait();
        }catch(InterruptedException ie){
            System.out.println("Interrupted exception in printOdd()");
            ie.printStackTrace();
        }
        isEven = true;
        System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
        intCurrNum += 1;
        notifyAll();
    }
}

synchronized void printEven(){
    while(!isEven){
        try{
            wait();
        }catch(InterruptedException ie){
            System.out.println("Interrupted exception in printEven()");
            ie.printStackTrace();
        }
        isEven = false;
        System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
        intCurrNum += 1;
        notifyAll();
    }
}
}
class ThreadOdd extends Thread {
PrintClass pc = null;

ThreadOdd(PrintClass pc , String name){
    super(name);
    this.pc = pc;
}

public void run(){
    for (int i = 0; i < 10; i++) {
        pc.printOdd();
    }
}
}
class ThreadEven extends Thread {
PrintClass pc = null;

ThreadEven(PrintClass pc,String name){
    super(name);
    this.pc = pc;
}

public void run(){
    for (int i = 0; i < 10; i++) {
        pc.printEven();
    }
}
}
public class EvenOddPrintClass {
public static void main(String[] args){
    PrintClass pc = new PrintClass();
    Thread to = new ThreadOdd(pc,"ThreadOdd");
    Thread te = new ThreadEven(pc,"ThreadEven");
    to.start();
    te.start();
}
}
class打印类{
int intCurrNum;
私有布尔值isEven=false;
同步的void printOdd(){
while(isEven){
试一试{
等待();
}捕获(中断异常ie){
System.out.println(“printOdd()中的中断异常”);
即printStackTrace();
}
isEven=真;
System.out.println(“线程名称=“+Thread.currentThread().getName()+”==Number=“+intCurrNum”);
intCurrNum+=1;
notifyAll();
}
}
同步的void print偶数(){
而(!isEven){
试一试{
等待();
}捕获(中断异常ie){
System.out.println(“print偶数()中的中断异常”);
即printStackTrace();
}
isEven=假;
System.out.println(“线程名称=“+Thread.currentThread().getName()+”==Number=“+intCurrNum”);
intCurrNum+=1;
notifyAll();
}
}
}
类ThreadOdd扩展线程{
PrintClass pc=null;
ThreadOdd(PrintClass pc,字符串名称){
超级(姓名);
this.pc=pc;
}
公开募捐{
对于(int i=0;i<10;i++){
pc.printOdd();
}
}
}
类Thread偶而扩展线程{
PrintClass pc=null;
Thread偶数(PrintClass pc,字符串名称){
超级(姓名);
this.pc=pc;
}
公开募捐{
对于(int i=0;i<10;i++){
pc.printfeen();
}
}
}
公共类{
公共静态void main(字符串[]args){
PrintClass pc=新的PrintClass();
螺纹至=新螺纹奇数(pc,“螺纹奇数”);
螺纹te=新的螺纹平衡(pc,“螺纹平衡”);
to.start();
te.start();
}
}

谢谢。

很有趣。因此,最初的
isEven=false
。如果先调用
printOdd()
,则
while(isEven)
测试为false,因此
printOdd()
将立即退出,而不生成任何输出。第一个程序中的
while
循环仅包含
wait
测试,而不是整个方法

然后,当另一个线程调用
print偶数()
时,它将调用
wait()
并挂起,因为没有其他线程可以调用
notifyAll()


您应该只需要
while
循环
wait
,因为在打印出偶数或奇数后您将退出,对吗?因此,第一个程序中的逻辑是正确的。

在两个版本中,isEven都以false开头

在第一个版本中,printOddNumber将跳过整个
,而
循环,打印奇数,将IsEvent设置为true并通知
偶数
线程,该线程将按顺序打印偶数并再次通知
奇数
线程等


在第二个版本中,printOddNumber将跳过整个
循环,包括打印数字和通知
偶数
线程。在10次尝试后,它将在没有打印任何内容的情况下退出,并在没有通知它的情况下使
线程挂起。

我建议您在调试器中运行代码并逐步完成这两个线程。这很有教育意义。您将看到错误的确切位置。

这与作业有关吗?如果一个线程处于“挂起”状态,可能是因为第一个线程锁定了第二个线程试图锁定的资源;或者,它可能在等待信号,但线程一从未发出信号。我们需要知道
wait
函数中的内容,否则很难判断。@Lirik:这是java.lang.Object中的wait方法。另一个线程一直在等待另一个线程在printOdd/print偶数方法末尾使用notifyAll调用唤醒它,但它们可能会在方法同步时卡住,或者另一个线程从while循环中失败,而另一个线程被卡住等待():in for The notify。@esaj。。。哦,明白了。我忘了!很抱歉,我不想将sleep()用于此目的。
public class CountDownApp
 {
 public static void main(String[] args)
 {
 Thread count1 = new CountDownEven();
 Thread count2 = new CountDownOdd();
 count1.start();
 count2.start();

 }
 }

 class CountDownEven extends Thread
 {
 public void run()
 {
 for(int i=10;i>0;i-=2)
 { 
 System.out.print(+i+"-");

 try {
    Thread.sleep(2);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
 }
 }

 }

 class CountDownOdd extends Thread 
 {
 public void run()
 {
 for(int i=9;i>0;i-=2)
 {
 System.out.print(+i+"-");

 try {
        Thread.sleep(2);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 }
 }

 }