Mark Ceitlin
Mark Ceitlin

Reputation: 93

How to make 2 threads share data? (Java)

I'm currently practicing Threads so I tasked myself to write a program that will create 2 threads. The first one will endlessly print a character and the second one will endlessly wait for input and then pass it to the first Thread. Then Thread #1 should print the passed character. Here's what I wrote:

public class A extends Thread {
                public char dif;
                Scanner stdin = new Scanner(System.in);
                @Override
                public void run() {
                    for (; ; ) {
                        dif = stdin.nextLine().charAt(0);
                        MyThread.setCh(dif);
                    }
                }
}

This thread takes input and then passes it to this one:

public class MyThread extends Thread {
    public static char ch;
    public static void setCh(char cha) {
        ch = cha;
    }
    public static char getCh() {
        return ch;
    }
    @Override
    public void run() {
        for(;;) {
            try {
                Thread.sleep(300);
            }
            catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(getCh());
        }
    }
}

And what happens in the main():

MyThread endless = new MyThread();
       MyThread.setCh('$');
       A set = new A();
       endless.start();
       set.start();

However, this doesn't work as intended. No matter what I type, the program keeps printing $. Also for some reason the first time I type a character I get an Out of bounds exception.

Upvotes: 1

Views: 61

Answers (2)

Ruslan
Ruslan

Reputation: 6290

The problem actually you have it is quite small delay in Thread.sleep(300);

Try to set sleep for a few seconds Thread.sleep(5000);. You have to type something before it will print previous char

Upvotes: 1

Oleksii Zghurskyi
Oleksii Zghurskyi

Reputation: 4365

Probably, the easiest way to approach this, is to use BlockingQueue.

Effectively, in your example the thread, that receives character from System.in is producer and the thread that prints received character is consumer.

So, here is the code that achieves your goal:

import java.util.*;
import java.util.concurrent.*;

class Setup {
   public static void main(String[] args) {
     BlockingQueue<Character> q = new LinkedBlockingQueue<>();
     Producer p = new Producer(q);
     Consumer c = new Consumer(q);
     new Thread(p).start();
     new Thread(c).start();
   }
}

class Producer implements Runnable {
   private final BlockingQueue<Character> queue;
   private final Scanner scanner = new Scanner(System.in);
   Producer(BlockingQueue<Character> q) { queue = q; }
   public void run() {
     try {
       while (true) { 
         queue.put(produce()); 
       }
     } catch (InterruptedException ex) {
       Thread.currentThread().interrupt();  // set interrupt flag
     } finally {
       scanner.close();
     }
   }
   Character produce() {
      return scanner.nextLine().charAt(0);
   }
}

class Consumer implements Runnable {
   private final BlockingQueue<Character> queue;
   Consumer(BlockingQueue<Character> q) { queue = q; }
   public void run() {
     try {
       while (true) { 
         consume(queue.take()); 
       }
     } catch (InterruptedException ex) {}
   }
   void consume(Character c) { 
     System.out.println("Received character: " + c);
   }
}

Upvotes: 1

Related Questions