简体   繁体   English

Java线程等待,在一个类中通知,给出意外结果

[英]Java Threads wait, notify in one class giving unexpected results

/ I had written the below program to wait() and notify(). / 我已经将以下程序编写为wait()和notify()。 But after going to First put() method, the threads are not going forward. 但是在转到First put()方法之后,线程不再前进。 Can anybody explain me what is the error I had done in the below code. 谁能解释一下我在以下代码中所犯的错误。 / /

public class ThreadJoin {
    public void buildThread() throws InterruptedException {
        Adder a = new Adder("Test");
        Thread t1 = new Thread(a, "First");
        Thread t2 = new Thread(a, "second");

        t1.start();
        t2.start();
    }

    public static void main(String[] args) throws InterruptedException {
        new ThreadJoin().buildThread();
    }
}

class Adder implements Runnable {
    String name;
    int i;
    private boolean suspendFlag = false;

    public Adder(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
            for(int i = 0; i < 10; i++){
                put(i);
            }

            for(int j = 0 ; j < 10; j++){
                get();
            }
    }

    public synchronized void put(int i) {
        this.i = i;

        try {
            while (suspendFlag) {
                wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("put: " + i+" currentThread: "+Thread.currentThread().getName());
        suspendFlag = true;
        notify();
    }

    public synchronized void get() {
        System.out.println("Entering into the get method");

        try {
            if (!suspendFlag) {
                wait();
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("get: " + i+" currentThread: "+Thread.currentThread().getName());
        suspendFlag = true;
        notify();
    }
}

Whichever thread executes first (say First ) will execute the synchronized put method, locking the monitor of the Adder object. 哪个线程First执行(例如First )将执行synchronized put方法,从而锁定Adder对象的监视器。 While this is happening, the other thread ( second ) cannot start executing the put method since it cannot lock the monitor of the same Adder object. 在这种情况下,另一个线程( second )无法开始执行put方法,因为它无法锁定同一Adder对象的监视器。

So First sees that suspendFlag is false and therefore skips the while . 因此, First看到suspendFlagfalse ,因此跳过了while It makes supsedFlag true and calls notify() . 它使supsedFlag true并调用notify() There is currently no thread waiting on the Adder object, so the call to notify() does nothing. 当前没有线程正在Adder对象上等待,因此对notify()的调用没有任何作用。

When this thread ends execution of the put method, the monitor is released and second potentially gets it. 当此线程结束put方法的执行时,监视器将被释放, second可能获取它。 If this happens, it sees that suspendFlag is true and enters the while block, executing wait() . 如果发生这种情况,它将看到suspendFlagtrue并进入while块,执行wait() Doing so, it releases the monitor. 这样做会释放监视器。 suspendFlag remains true . suspendFlag仍然为true

Execution returns to First , which loops its for and reinvokes put . 执行返回到FirstFirst循环进行for然后重新调用put It sees that suspendFlag is true and enters the while loop, invoking wait() . 它看到suspendFlagtrue并进入while循环,并调用wait()

Now both your threads are in wait and there is nothing to notify them. 现在,您的两个线程都处于wait ,没有任何notify Your program stalls. 您的程序停顿了。

The simple view of what is going on is that you have a wait-notify structure that forces alternate put and get calls. 发生的情况的简单视图是,您有一个等待通知结构,该结构强制进行交替的putget调用。 You have two threads, each of which is going to do 10 put calls before its first get , so the alternation is not possible. 您有两个线程,每个线程put在其第一个get之前执行10次put调用,因此无法进行交替。 Both threads end up in put waiting for the other to do a get . 这两个线程最终都put等待另一个进行get

You could change your design to allow multiple put calls without a get , or change the driving code so that one thread does put calls and the other does get calls. 你可以改变你的设计允许多put电话没有get或更改驱动代码,这样一个线程并put通话,另一种则get调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM