Java how to synchronize 2 threads? - java

SOLVED !
I have a homework. I will say shortly what is about. I have to read from .txt file few numbers, and multiply them. I need to use threads and synchronize that multiplication only. I done that already and my homework ends here! But, I want to go ahead and create a more complex way for example:
I have in .txt numbers like this: 5, 6, 2, 11, 24, 10,
and then I multiply them like this 5*6*2*11*24*10 .
How can I create 2 threads, Thread #1 for numbers, and Thread #2 for multiply, and print them in console like this:
Thread #1 running, number is 5
Thread #2 running, multiply is 5
Thread #1 running, number is 6
Thread #2 running, multiply is 30
Thread #1 running, number is 2
Thread #2 running, multiply is 60
I really appreciate any suggestion, past 10 h since I work at this and still can't get it work.
class MyThread extends Thread {
Thread thread;
MyThread(String name) {
thread = new Thread(this, name);
}
public synchronized void numbers(boolean running) {
if (!running) {
notify();
return;
}
notify();
try {
FileInputStream fs = new FileInputStream("in.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String line;
int numbers = 0;
while ((line = br.readLine()) != null) {
String[] splitter = line.split("\\s");
numbers = Integer.parseInt(splitter[0]);
for (int i = 0; i <= splitter.length - 1; i++) {
numbers = Integer.parseInt(splitter[i]);
System.out.print("\nIn " + thread.getName() + "number is " + numbers + "\t");
Thread.sleep(500);
}
}
} catch (InterruptedException e) {
System.out.println("main thread interrupted");
} catch (IOException e) {
System.out.println("main thread interrupted");
}
}
public synchronized void multiply(boolean running) {
if (!running) {
notify();
return;
}
notify();
try {
FileInputStream fs = new FileInputStream("in.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String line;
int numbers = 0;
int multiply = 1;
while ((line = br.readLine()) != null) {
String[] splitter = line.split("\\s");
numbers = Integer.parseInt(splitter[0]);
for (int i = 0; i <= splitter.length - 1; i++) {
numbers = Integer.parseInt(splitter[i]);
multiply = multiply * numbers;
System.out.print("\nIn " + thread.getName() + " multiply is " + multiply + "\t");
Thread.sleep(500);
}
}
} catch (InterruptedException e) {
System.out.println("main thread interrupted");
} catch (IOException e) {
System.out.println("main thread interrupted");
}
}
synchronized public void run() {
if (thread.getName().compareTo("Thread #1 ") == 0) {
for (int i = 0; i < 1; i++)
this.numbers(true);
this.numbers(false);
} else {
for (int i = 0; i < 1; i++)
this.multiply(true);
this.multiply(false);
}
}
}
My code look like this:
In main I call like this:
MyThread mt1 = new MyThread("Thread #1 ");
MyThread mt2 = new MyThread("Thread #2 ");
mt1.start();
mt2.start();
At this moment , my output look like this:
In Thread #2 multiply is 5
In Thread #1 number is 5
In Thread #1 number is 6
In Thread #2 multiply is 6
In Thread #2 multiply is 30
In Thread #1 number is 2
In Thread #1 number is 11
In Thread #2 multiply is 660
In Thread #2 multiply is 15840
In Thread #1 number is 24

The problem is that you're trying to use one implementation for both tasks. I would suggest to create ReadThread that will read the input file and MultiplyThread that will wait for some event for example and multiply numbers. Also they will need to share some collection of the numbers (see ConcurrentLinkedQueue for example).
So ReadThread read a number from file, adds it to the queue. At the same time MultiplyThread waits for anything to appear in the same queue and when this happens multiply new number on the previous one. There is also will be improvements on the design, because without much effort we can replace MultiplyThread with let's say AddThread that will calculate sum of the numbers.
However your implementation trying to do both tasks in one class which highly increases complexity. Also try to get rid of synchronized and Thread.sleep statements, in your case they will decrease the performance and there would be no point in using multithreading.
Here is example implementation for the method I've suggested.
First is the ReadThread. It has the queue that will contain numbers that have to be processed. I have simplified the reading of the numbers from the file, you can replace it with you reading implementation.
class ReadThread implements Runnable {
private final String filename;
private final ConcurrentLinkedQueue<Integer> queue;
public ReadThread(ConcurrentLinkedQueue<Integer> queue, String filename) {
this.queue = queue;
this.filename = filename;
}
public void run() {
try {
FileInputStream fs = new FileInputStream(filename);
Scanner scanner = new Scanner(fs);
while (scanner.hasNextInt()) {
int number = scanner.nextInt();
System.out.println("ReadThread read " + number);
queue.add(number);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
And the MultiplyThread. Here we take the number from the queue and multiply it on the result which stores the previous value. There is the problem with thread life cycle - we don't know when it should be stopped. So I have used simple active flag. Which tells the thread when to stop.
class MultiplyThread implements Runnable {
private boolean active = true;
private Integer result = 1;
private final Queue<Integer> queue;
public MultiplyThread(ConcurrentLinkedQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
while (isActive()) {
Integer number = queue.poll();
if (number != null) {
result *= number;
System.out.println("MultiplyThread current result is " + result);
}
}
}
public synchronized void stop() {
active = false;
}
public synchronized boolean isActive() {
return active;
}
}
And here is the last part. It's more complex then yours, because of MultiplyThread interruption.
public static void main(String[] args) throws InterruptedException {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
ReadThread readThread = new ReadThread(queue, "numbers.txt");
MultiplyThread multiplyThread = new MultiplyThread(queue);
Thread reader = new Thread(readThread);
Thread multiplicator = new Thread(multiplyThread);
multiplicator.start();
reader.start();
reader.join();
multiplyThread.stop();
multiplicator.join();
}
The result of the program
ReadThread read 1
ReadThread read 2
MultiplyThread current result is 1
MultiplyThread current result is 2
ReadThread read 3
MultiplyThread current result is 6
ReadThread read 4
MultiplyThread current result is 24
ReadThread read 5
MultiplyThread current result is 120
ReadThread read 6
MultiplyThread current result is 720
ReadThread read 7
MultiplyThread current result is 5040
You can see that thread are working concurrently, ReadThread does not wait MultiplyThread to calculate the result for all previous values.

It is not clear what you are trying to do. There are some obvious mistakes in the code which i want to highlight (and hence writing this answer), but I can't answer the question as the code seems to do what it was written to do: it runs 2 threads, both read from the same file and output results of reading in slightly different ways.
Now to the problems:
1) if you are extending Thread you should not have a thread field inside of it. Basically you can replace thread = new Thread(this ,name); with super(name).
2) your synchronized doesn't do anything. Synchronized makes method enter a monitor (essentially acquire object lock) when you enter the method and release it when method is done. Your two threads are 2 different instances which share no data between each other, so synchronizeds are not doing anything.

The way you've written your code, the two threads aren't really "connected", they don't share any memory. They read both the same file, but that's all - no shared memory. From what I guess, the idea would rather to have a "producer" thread which reads data from the file, and a "consumer" thread which get data read by the first thread and execute the multiplication. The second thread should not read the file.
You could write something with a shared AtomicInteger: when empty (null), the "producer" thread set it to what it has read ; and when non empty, the "consumer" thread read it, reset it to empty, and can run its multiplication.

Related

Who can explain the result?

public class Bank {
private int sum=0;
public void add(int n) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
sum+= n;
System.out.println(sum);
}
}
public class Consumer implements Runnable {
Bank bank = new Bank();
#Override
public void run() {
for (int i = 0; i < 10; i++) {
bank.add(100);
}
}
}
public class Tes2 {
public static void main(String[] args) {
Consumer consumer = new Consumer();
Thread thread1 = new Thread(consumer);
Thread thread2 = new Thread(consumer);
thread1.start();
thread2.start();
}
}
This is a multithreaded program, simulation is multiple depositors to the bank to deposit money, used to demonstrate multithreaded security issues.Since the code is not synchronized, its first and second results might be 200/200,200/300, and so on.But I don't understand why you get 100/100, who can explain?
This is a race condition.
Both threads have access to sum.
sum += n; is not atomic
Thread 1 reads sum 0
Thread 2 swaps in because the code isnt synchronized reads sum as 0
Thread 1 adds 100 to 0 and writes that to sum
Thread 2 adds 100 to 0 and writes that to sum overwriting thread 1s value
If you think about the concurrency of this program just based on the lines in the code, the 100/100 output result wouldn't make sense. But you also have to think about what instructions are actually happening when these lines are being performed. Each line of code can consist of many, many assembly instructions. In this case, to add n to sum, what really happens is that the value of sum is read from memory, probably loaded onto a register, incremented, then re-written onto memory.
The 100/100 output can happen in the following scenario. Let's say thread 1 and thread 2 both call bank.add(100), and the bank handles requests asynchronously. That is, the bank has a thread handling each request.
Then, thread 1 of the bank loads the value of sum, which is zero. Thread 2 also loads the value of sum right after, which is still zero. Then, thread 1 takes the value it loaded, adds n=100, and writes it into memory. Thread 2 does the same; it takes the value of sum it loaded previously, 0, adds 100, then writes it back onto memory. Then, they each print out the value of 100.

Thread.sleep(time) is not working the way I need it to. I need something better

I'm a student in Denmark trying to make a school project. What I'm working on at this moment is a reader class that takes in a string then prints out word by word and/or letter by letter.
I did some research and found out that Thread.sleep(time) did exactly what I needed it to do. But after I used it I found out it does not work properly! I tried to research some more and found something called a ThreadPoolExecutor but I can figure out how it works in my case.
My reader:
public class TextReader {
// Print method to print word by word from a string
public void wordByWord(String text) throws InterruptedException {
String[] words = text.split(" ");
for (int i = 0; i < words.length; i++) {
System.out.print(words[i] + " ");
Thread.sleep(250);
}
}
// Print method to print letter by letter from a string
public void letterByLetter(String text) throws InterruptedException {
String[] words = text.split(" ");
for (int i = 0; i < words.length; i++) {
String word = words[i] + " ";
char[] letters = (word.toCharArray());
for (int j = 0; j < letters.length; j++) {
System.out.print(letters[j]);
Thread.sleep(250); //so it does not print all the letters at once
}
}
}
}
The reason why Thread.sleep(time) not works in my case is because I need to print to the console and by using Thread.sleep(time) it does not print like a waterfall. It prints either the string I'm trying to break down (time lower than 250ms) or a few letters a once (250 ms) or is just so slow I can't look at it... (over 250ms). I need it to run fast and smooth! So it looks like someone is writing it.
I think I successfully recreated your problem. Every delay lower than about 205 ms seem to cause updating problems. Sometimes the words/letters don't appear but then at the next interval multiple words/letters appear at the same time.
This seems to be a limitation of the Console I/O performance (See this answer). There isn't really anything you can do about this. If you want to output text with a short, minimal delay like this, you need to program your own GUI (for example JavaFX). This will probably solve the performance issues.
Outputs at different delays
205 ms
190 ms
Thread's sleep method takes milliseconds to stop the execution of current thread for specified milliseconds. If it's slow, you can pass less MS and if it's fast then you can increase the timings. So you can tweak according to your need.
ExecutorFramework is a different thing.
It a way to submit your runnable task to the threads managed by ExecutorFramework.
What you are doing is putting a Thread to sleep for that time. That means the thread will become unblocked after that time, however you aren't accounting for the overhead of context switching from another thread. What you want is something more like this
Tried out the ScheduledExecutorService approach and seems to work fine. There's some optimization to be done and some hoops to jump through to wait for the scheduled printing to finish, but it doesn't seem to display the lag (in the two consoles I tried - Eclipse output and Windows Bash).
public class Output {
public static void main(String[] args) {
String toPrint = "Hello, my name is Voldemort, but few call me that.";
StringPrinter printer = new StringPrinter();
printer.print(toPrint, Output::byCharacter, 30);
System.out.println();
printer.print(toPrint, Output::byWord, 150);
}
private static List<String> byWord(String toSplit) {
Iterable<String> it = () -> new Scanner(toSplit);
return StreamSupport.stream(it.spliterator(), false).map(s -> s + " ").collect(Collectors.toList());
}
private static List<String> byCharacter(String toSplit) {
return toSplit.chars().mapToObj(i -> "" + (char) i).collect(Collectors.toList());
}
}
class StringPrinter implements Runnable {
// using an array to be most efficient
private String[] output;
private int currentIndex;
// the service providing the milliseconds delay
private ScheduledExecutorService printExecutor;
public void print(String toOutput, Function<String, List<String>> split, int delay) {
if (printExecutor != null) {
throw new IllegalStateException();
}
printExecutor = Executors.newSingleThreadScheduledExecutor();
List<String> list = split.apply(toOutput);
output = list.toArray(new String[list.size()]);
currentIndex = 0;
printExecutor.scheduleWithFixedDelay(this, 0, delay, TimeUnit.MILLISECONDS);
// wait until output has finished
synchronized (this) {
while (printExecutor != null)
try {
wait(); // wait for printing to be finished
} catch (InterruptedException e) {}
}
}
#Override
public void run() {
if (currentIndex < output.length) {
System.out.print(output[currentIndex++]);
} else {
// mark this print run as finished
printExecutor.shutdown();
printExecutor = null;
synchronized (this) { notifyAll(); }
}
}
}

Read from stdin but unable to know when to stop

I am running some commnads on commmand prompt. I am waiting for the last command's output to complete. I have to read the output and perform the operation. My command's output is very dynamic and I can not predict when I can stop reading.
I am having issues that I dont know when to stop reading. If suppose I keep the while read(), then my last command output is not ending with new line. Is there any mechenism which can tell me if there has been no activity on stdin for last 5mins, then I get some alert??
The approach I took was to create a class implementing Runnable which monitors the value of a shared AtomicInteger flag. This InputRunnable class sleeps for 5 minutes (300000 ms) and then wakes up to check whether the value has been set by the main method. If the user has entered at least one input in the last 5 minutes, then the flag would be set to 1, and InputRunnable will continue execution. If the user has not entered an input in the last 5 minutes, then the thread will call System.exit() which will terminate the entire application.
public class InputRunnable implements Runnable {
private AtomicInteger count;
public InputRunnable(AtomicInteger count) {
this.count = count;
}
public void run() {
do {
try {
Thread.sleep(300000); // sleep for 5 minutes
} catch (InterruptedException e) {
// log error
}
if (count.decrementAndGet() < 0) { // check if user input occurred
System.exit(0); // if not kill application
}
} while(true);
}
}
public class MainThreadClass {
public static void main(String args[]) {
AtomicInteger count = new AtomicInteger(0);
InputRunnable inputRunnable = new InputRunnable(count);
Thread t = new Thread(inputRunnable);
t.start();
while (true) {
System.out.println("Enter a number:");
Scanner in = new Scanner(System.in);
int num = in.nextInt(); // scan for user input
count.set(1);
}
}
}
I tested this code locally and it appears to be working, but please let me know if you have any issues getting it to run on your system.

Runnable run() function terminates immediately [duplicate]

This question already has an answer here:
Odd behavior with Runnable and ExecutorService
(1 answer)
Closed 9 years ago.
I'm currently trying to multithread a previous program of mine. Here is the code below:
public class DipoleTester {
public static String DIR = "/home/";
public static void main(String[] args) throws InterruptedException {
Dipole trial;
ExecutorService service =
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (int r = 10; r < 150; r += 1) {
double radius = (double) r / 10000.0;
for (int matType = 0; matType < 3; matType++) {
String name = matType + "_rad" + radius;
trial = new DipoleSimple(DIR, name);
trial.materialType = matType;
trial.RADIUS = radius;
service.submit(trial);
}
}
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);
}
}
It's a pretty straightforward program. run() is just a pretty basic method that used to be the main() method. On average it takes about 3 minutes to evaluate. The problem is that here, it seems like it's just making an asynchronous call to run() because it evaluates the entire threadpool instantly.
i.e. i'm expecting it to run say 8 threads in parallel in 3-5 minutes. But instead, it runs each one and says it's completed practially instantly and loads up the next thread in the threadpool. So I'm left with a couple hundred threads that are all trying to run simultaneously.
Any idea what's going on?
Your code looks fine, I tried following sample to test it out:
System.out.println("Available Processors: "+Runtime.getRuntime().availableProcessors());
ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final AtomicInteger ai = new AtomicInteger();
for(int i=0; i<10; i++) {
es.submit(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"_"+ai.incrementAndGet());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
System.out.println("shutting down");
es.shutdown();
System.out.println("shutdown");
es.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);
System.out.println("Completed");
Sample output (consider 4 available processor):
Available Processors: 4
pool-1-thread-2_1
pool-1-thread-3_3
pool-1-thread-4_4
pool-1-thread-1_2
shutting down
shutdown
pool-1-thread-2_5
pool-1-thread-4_6
pool-1-thread-3_7
pool-1-thread-1_8
pool-1-thread-2_9
pool-1-thread-4_10
Completed
Since you are not submitting additional trials after shutdown, all submitted trials must be getting processed as you can see above all 10 threads submitted before shutdown completes. You can verify this by logging run method completion log/statement. Further it would be helpful to analyze if you can add time logs as how much time run method is taking by each thread when you run your actual code.

Synchronization of many objects and counter

I know it lot of people have problems with this topic and you might be bored, but I try to understand it since few days and still don't know how it works:(. I have a counter object, and other objects of another class (in the future more then one class). Now each object should respond for counters execution. One count - one step of each objects run method. That's my code:
public class Th {
private final static Object lock1 = new Object();
////////////////////////////////////////////////////////////////////////////////
private class Stop implements Runnable {
private int count, id;
public Stop(int id) {
this.count = 0;
this.id = id;
}
#Override public void run() {
synchronized(lock1){
while (count < 20) {
try {
lock1.wait();
}
catch (InterruptedException exception) {
System.out.println("Error!");
}
System.out.println(count + " stop " + id);
this.count++;
// try {
// Thread.sleep(360);
// }
// catch (InterruptedException exception) {
// System.out.println("Error!");
// }
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
private class Counter implements Runnable {
private int count;
public Counter() {
this.count = 0;
}
#Override public void run() {
synchronized(lock1){
while (count<15) {
lock1.notifyAll();
System.out.println(count + " counter");
this.count++;
// try {
// Thread.sleep(360);
// }
// catch (InterruptedException exception) {
// System.out.println("Error!");
// }
}
}
}
}
public void test() {
Stop s1 = new Stop(1);
Stop s2 = new Stop(2);
Stop s3 = new Stop(3);
Counter counter = new Counter();
(new Thread(s1)).start();
(new Thread(s2)).start();
(new Thread(counter)).start();
(new Thread(s3)).start();
}
}
and it returns me something like:
run:
0 counter
1 counter
2 counter
3 counter
4 counter
5 counter
6 counter
7 counter
8 counter
9 counter
10 counter
11 counter
12 counter
13 counter
14 counter
0 stop 1
what I need is:
0 counter
0 stop 0
0 stop 1
0 stop 2
1 counter
1 stop 0
1 stop 1
1 stop 2
2 counter
2 stop 0
2 stop 1
2 stop 2
3 counter
...
The entire loop of the Counter thread is synchronizd on lock1. This means that although you call notifyAll in this loop, other threads can't reacquire the lock until the complete loop has ended in the Counter thread.
Make each iteration of the loop synchronized, instead of synchronizing outside of the loop.
Note that this won't be sufficient, though, because the Counter thread might reacquire the lock before all the Stop threads have reacquired it. You'll need to make the Counter thread wait on another condition, and make it restart when all the Stop threads have displayed the count.
You should investigate higher-level abstractions, like CyclicBarrier and CountDownLatch.
First, the best way to solve this is to use the higher level synchronization classes, as JB Nizet says.
But if you want to do it "the hard way" as a learning exercise, you need to recognize that this problem requires the Counter and Stop threads to wait for specific "events".
The Stop threads need to wait until the Counter thread tells them to advance to the next stop.
The Counter thread needs to wait until all Stop threads have advanced and stopped.
One problem with your current implementation is that the Counter thread has nothing to tell it when all of the Stop threads have advanced and stopped. Instead, it assumes that when it sees a notify event that it is ok to issue the next count.

Categories