简体   繁体   中英

Inter thread Communication-Java

I am new to java thread. I am unable to give the lock back to the thread from the main thread in the following code. I am getting the undesired output because i am unable to unlock the thread. I want thread to increment the value using thread (goes to wait state after that) and after printing the value, release the lock to print the next incremented value.

   class Foo implements Runnable 
    {
         public volatile int value=0,i=0;
        Thread t=new Thread();
       public void method(Thread t) 
        {
          this.t = t;
       }

         @Override
         public synchronized void run() 
         {

            while(i<3)
            {
            value++;//receive and process ACK
             i++;
            try
            {
           System.out.println("im thread here");
            wait();  
            System.out.println("passed wait");
            }
            catch(InterruptedException ex){
            }
            System.out.println("im notified");
             }//while 
             //}//sync
         }//run method

         public int getValue()
         {

             try
        {
          Thread.sleep(1000);
        }
         catch (Exception e) {
          System.out.println(e);
        } 
             return value;
         }
     }//class foo

     public class ThreadTest
    {
      public static int value1,times=0;
      public static void main(String[] args) 
      {
        Foo foo=new Foo();
        Thread t=new Thread(foo);
        foo.method(t);
        t.start();
        while(times<3)
        {   
             synchronized(t)
           {
           value1=foo.getValue();
           times++;
           System.out.println(value1);
           System.out.println(t.getState()); 
               try
            {
            t.notify();
             System.out.println("Notify is reached");
             }
            catch(IllegalMonitorStateException ex)
            {
            System.out.println("Thread is blocked");
            } 
        }//sync
        }//while
       }//main
    }//mclasss

It is very unclear what you really want to do but we will assume here that you want to run a thread in the background which should run only when its spawner (let's say the main thread) allows it to.

The JDK has several tools for this already, no need to rely on the low level wait() and notify{,All}() methods.

One example of such a primitive is a CountDownLatch . It is a one-use entity which allows you to specify the times a given set of threads should countDown() it before any threads .await() ing for them can trigger.

In combination with the multithread handling classes which appeared as far back as Java 1.5, this means you could do something like this:

// Implementation of a Runnable waiting for the counter to trigger
public final class MyWaitingClass
    implements Runnable
{
    private final CountDownLatch latch;

    public MyWaitingClass(final CountDownLatch latch)
    {
        this.latch = latch;
    }

    @Override
    public void run()
    {
        try {
            latch.await();
            // do whatever is necessary
        } catch (InterruptedException e) {
            // Argh; interrupted before the latch was released
            Thread.currentThread().interrupt();
        }
    }
}

// In the main class:
final ExecutorService executor = Executors.newSingleThreadPool();
final CountDownLatch latch = new CountDownLatch(1); 
final Runnable runnable = new MyWaitingClass(latch);
executor.submit(runnable);
// do whatever is needed; then:
latch.countDown();

Are you trying to do something like this? If you really must use wait/notify & want to use Runnable.

I added a wait block, otherwise the main thread may finish before the background thread increments the value.

class Foo implements Runnable {
    public volatile int value = 0, i = 0;
    private Thread backgroundThread;

    public void setThread(Thread thread) {
        this.backgroundThread = thread;
    }

    @Override
    public void run() {
        synchronized (backgroundThread) {
            while (i < 2) {
                value++;
                i++;
                backgroundThread.notify();
                try {
                    System.out.println("background thread wait start");
                    backgroundThread.wait();
                    System.out.println("background thread notified");
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    public int getValue() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }
}

public class ThreadTest {
    public static int value1, times = 0;

    public static void main(String[] args) {
        Foo foo = new Foo();
        final Thread thread = new Thread(foo);
        foo.setThread(thread);
        thread.start();

        while (times < 3) {
            synchronized (thread) {
                value1 = foo.getValue();
                times++;
                System.out.println(value1);
                System.out.println(thread.getState());
                thread.notify();
                try {
                    thread.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Or you can extend thread:

class BackgroundThread extends Thread {
    public volatile int value = 0, i = 0;

    @Override
    public synchronized void run() {
        while (i < 2) {
            value++;
            i++;
            notify();
            try {
                System.out.println("background thread wait start");
                wait();
                System.out.println("background thread notified");
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    public int getValue() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }
}

public class ThreadTest {
    public static int value1, times = 0;

    public static void main(String[] args) {
        BackgroundThread backgroundThread = new BackgroundThread();
        backgroundThread.start();

        while (times < 3) {
            synchronized (backgroundThread) {
                value1 = backgroundThread.getValue();
                times++;
                System.out.println(value1);
                System.out.println(backgroundThread.getState());
                backgroundThread.notify();
                try {
                    backgroundThread.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

You can get detailed information about inter-thread communication from this link. https://igniteddevelopers.in/Adv-java/InterThreadCommunication

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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