I need to run a java program called ArrayHolder that will run two Threads. ArrayHolder will have an Array. ThreadSeven will overwrite every element of that Array with 7, and ThreadOne with 1.
The result after execution should be 7,1,7,1,7,1,7,1 etc. I have solved this problem, although I dont like my solution and was hoping you could suggest a better way.
p.s: Both Threads must write on all indexes.
public class ArrayHolder {
private int[] array = {1, 2, 3, 4, 5, 6, 4, 8, 9, 10};
public void writeInt(int pos, int num) {
array[pos] = num;
}
public static void main(String[] args) {
ArrayHolder holder = new ArrayHolder();
ThreadSeven seven = new ThreadSeven(holder, null);
Runnable one = new ThreadOne(holder, seven);
Thread thread1 = new Thread(seven);
Thread thread2 = new Thread(one);
seven.setThread(one);
thread1.start();
thread2.start();
holder.printArray();
}
private void printArray() {
for (int i = 0; i < 10; i++) {
System.out.println(array[i]);
}
}
public class ThreadSeven implements Runnable {
private ArrayHolder array;
private Runnable t;
private int flag=0;
#Override
public void run() {
for(int i=0;i<10;i++){
array.writeInt(i, 7);
flag=(flag+1)%2;
if (flag==0){
synchronized(t){
t.notify();
}
}else{
synchronized(this){
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(ThreadSeven.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public ThreadSeven (ArrayHolder ar,Runnable t){
array=ar;
this.t=t;
}
public void setThread(Runnable t){
this.t=t;
}
}
public class ThreadOne implements Runnable {
private ArrayHolder array;
private Runnable t;
private int flag = 0;
#Override
public void run() {
for (int i = 0; i < 10; i++) {
array.writeInt(i, 1);
flag = (flag + 1) % 2;
if (flag == 1) {
synchronized (t) {
t.notify();
}
} else {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(ThreadSeven.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public ThreadOne(ArrayHolder ar, Runnable t) {
array = ar;
this.t = t;
}
public void setThread(Runnable t) {
this.t = t;
}
}
ThreadSeven and ThreadOne don't need to be separate classes; is looks like you just copy/pasted the code, and then changed the 7 in writeInt to a 1. Instead, you can paramaterize this value and pass it in the constructor. Then you get something like:
public class ThreadWriter implements Runnable {
private final int numberToWrite;
// ...
public ThreadOne(ArrayHolder ar, Runnable t, int numberToWrite) {
array = ar;
this.t = t;
this.numberToWrite = numberToWrite;
}
// ...
}
Another point is that both of your threads have to know about each other; this doesn't scale well. Pretend that for your next assignment your teacher said that you have to handle three threads which write 1, 4, 7, 1, 4, 7, ...; you would have to change the implementation of ThreadOne and ThreadSeven. A better solution which you could make now is have the ThreadWriters themselves be dumber, and manage their interaction more in the ArrayHolder class (or with an intermediary ThreadWriterManager class).
Your solution has some problems and looks to me like it would not print the correct result.
a) You don't wait for the threads to finish before you print the resulting array
Add thread1.join() and thread2.join() before holder.printArray() in case it is not there yet.
b) both threads start with writing immediately via array.writeInt(0, /* 1 or 7 */); After that they start to wait on each other. Whether the first index is correct or not depends on luck.
c) Continuing after this.wait(); without a loop checking a condition is not safe since the interrupt could be caused by something else than the other thread. I guess it's okay to do that here since it's just an exercise.
d) I see a potential deadlock: let's assume both threads are still writing the first index. So both are not in a synchronized block.
The thread that has to notify the other one does so, writes the next index and goes into it's own wait block.
But the second thread was not waiting at the time so the notify from the first thread did nothing. Second thread goes into wait block too.
Now both threads wait on each other and nothing happens anymore.
I don't have a great simple solution for you since that problem is quite complex.
The 1-thread needs to start writing at index 0 then wait until the 7-thread has written index 0 and 1, now 1-thread writes index 1 and 2 and waits and so on. That is the only way I see possible to ensure that both thread have written to every index and that the result is 7-1-7-1-.... Synchronizing access inside ArrayHolder would be very tricky since it needs to make sure that both threads have written to each index in the correct order.
But I think your general idea is okay. You just need to make sure that it is safe
Related
I'm currently working on a problem where I have to:
Write out a letter, x amount of times, after x amount of ms. Use 4 multithreads, 3 of them start right away 1 of them starts when one of the 3 is finished.
For example: A, 10, 100, has to write out A ever 10 times every 100 miliseconds.
Im currently stuck on syncing the multithreads for them to work together at adding one sum rather than them working seporatley. Could you advise how to sync it together for it to write out the above?
Here is my code:
public class PrinterThread extends Thread {
private String letter;
private int internal;
private int amount;
public PrinterThread() {
for (int i = 1; i <= internal; i++) {
System.out.println(letter);
}
synchronized (this){
internal++;
}
try {
Thread.sleep(amount);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
PrinterThread printerThread = new PrinterThread();
PrinterThread printerThread1 = new PrinterThread();
PrinterThread printerThread2 = new PrinterThread();
PrinterThread printerThread3 = new PrinterThread();
printerThread.run();
printerThread1.run();
printerThread2.run();
printerThread3.run();
}
}
Use a BlockingQueue for synchronisation, but you do need to join with the threads from your main method otherwise your main will exit the JVM before the threads finish (or possibly even before they start).
public class PrinterThread implements Runnable {
private String letter;
private int copies;
private int amount;
public PrinterThread(String letter, int copies, int amount) {
this.letter = letter;
this.copies = copies;
this.amount = amount;
}
public void run() {
for (int i = 0; i < copies; i++) {
System.out.println(letter.repeat(copies));
try {
Thread.sleep(amount);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
QUEUE.offer(0);
}
}
public class Main {
private static BlockingQueue<Integer> QUEUE = new ArrayBlockingQueue<>(4); // at least as large as the number of threads
public static void main(String[] args) {
Thread printerThread1 = new Thread(new PrinterThread("A", 10, 100));
Thread printerThread2 = new Thread(new PrinterThread("B", 20, 50));
// etc
printerThread1.start();
printerThread2.start();
// etc
QUEUE.take(); // blocking call
new Thread(new PrinterThread("D", 30, 80)).start();
// wait for threads to finish
printerThread1.join();
printerThread2.join();
// etc
}
}
Disclaimer: This answer was thumbed in via my phone, so it may not work correctly or even compile, but there’s a good chance it will work.
Write out a letter, x amount of times, after x amount of ms. Use 4 multithreads, 3 of them start right away 1 of them starts when one of the 3 is finished.
You obviously need to create a PrinterThread constructor which takes the letter, the amount of times, and amount of millis.
I'm currently stuck on syncing the multithreads for them to work together at adding one sum rather than them working separately.
I'm not sure about the sum. If you are asking how you can start the 3rd thread then there are a number of different ways to do this. I would lock on a lock object and pass in a boolean in the constructor about whether or not the thread should wait() on the lock. As each of the other threads finish they would call notify() on the lock.
private static final Object lock = new Object();
...
public class PrinterThread {
public PrinterThread(char letter, int times, int millis, boolean waitForOthers) {
this.letter = letter;
this.times = times;
this.millis = millis;
if (waitForOthers) {
synchronized (lock) {
// wait for one of the others to notify us
lock.wait();
}
}
}
public void run() {
...
synchronized (lock) {
// notify the lock in case another thread is waiting
lock.notify();
}
}
Then start 3 PrinterThreads with a value of false and 1 of them with a value of true so that it waits.
It is my first time posting a question. So please, go easy on me. :D
I am a student and I currently learning about multithreading.
My task is to determine the sorting of an array by dividing the array into two equal halves and
start a thread for each half, each thread being responsible for sorting the numbers assigned to it.
The thread is looking at how many numbers need to be sorted. If this is more than
a certain threshold, the thread will create 2 new threads, each sorting one half of the list. When those
threads are finished, the thread will merge the two (sorted) arrays together again. This creates a 'tree'
of active threads.
Threads that are not going to 'outsource' their work sort the arrays again with bubble sort
This is my code for the MultiThreading class:
public class MultiThreading implements Runnable {
private int[] wholeNumbers;
private int threshold;
public int[] getWholeNumbers() {
return wholeNumbers;
}
public MultiThreading(int[] wholeNumbers, int threshold) {
this.wholeNumbers = wholeNumbers;
this.threshold = threshold;
}
#Override
public void run() {
try {
sortArray(wholeNumbers, threshold);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public int[] sortArray(int[] wholeNumbers, int threshold) throws InterruptedException {
if (wholeNumbers.length < threshold) {
Sort.bubbleSort(wholeNumbers);
} else {
int[] left = Arrays.copyOfRange(wholeNumbers, 0, wholeNumbers.length / 2);
int[] right = Arrays.copyOfRange(wholeNumbers, wholeNumbers.length / 2, wholeNumbers.length);
Thread leftThread = new Thread(new MultiThreading(left, threshold));
Thread rightThread = new Thread(new MultiThreading(right, threshold));
leftThread.start();
rightThread.start();
leftThread.join();
rightThread.join();
wholeNumbers = Sort.merge(left,right);
}
return wholeNumbers;
}
}
This is how I initialize the class (here I try to change an already defined wholeNumbers array):
MultiThreading multiThreading = new MultiThreading(wholeNumbers, threshold);
Thread thread = new Thread(multiThreading);
thread.start();
thread.join();
wholeNumbers = multiThreading.getWholeNumbers();
I have been provided with the sorting and merging method, so they work just fine.
My problem is that it does not return the sorted array. I am not sure how to fix that.
It would be great if I receive some guidance. Thanks in advance.
SOLUTION
It turned out that the values in the merge method are not the correct ones that I should have used.
To fix this problem, I initialized the MultiThreading class two times, added them to the Threads, and used a get method in the merging function.
By doing that I ensure that the merging method receives the bubble-sorted whole numbers.
Here is my new Multithreading class:
public class MultiThreading implements Runnable {
private int[] wholeNumbers;
private int threshold;
public int[] getWholeNumbers() {
return wholeNumbers;
}
public void setWholeNumbers(int[] wholeNumbers) {
this.wholeNumbers = wholeNumbers;
}
public MultiThreading(int[] wholeNumbers, int threshold) {
this.wholeNumbers = wholeNumbers;
this.threshold = threshold;
}
#Override
public void run() {
if (wholeNumbers.length > threshold) {
int[] left = Arrays.copyOfRange(wholeNumbers, 0, wholeNumbers.length / 2);
int[] right = Arrays.copyOfRange(wholeNumbers, wholeNumbers.length / 2, wholeNumbers.length);
MultiThreading leftM = new MultiThreading(left, threshold);
MultiThreading rightM = new MultiThreading(right, threshold);
Thread leftThread = new Thread(leftM);
Thread rightThread = new Thread(rightM);
leftThread.start();
rightThread.start();
try {
leftThread.join();
rightThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
setWholeNumbers(Sort.merge(leftM.getWholeNumbers(), rightM.getWholeNumbers()));
}
else {
Sort.bubbleSort(wholeNumbers);
}
}
}
Here is my code in the main class:
MultiThreading multiThreading = new MultiThreading(wholeNumbers, threshold);
Thread thread = new Thread(multiThreading);
thread.start();
thread.join();
wholeNumbers = multiThreading.getWholeNumbers();
I should learn to use a pen and paper, understand the logic and then code.
Thanks for the comments.
Below is a trivial java program. It has a counter called "cnt" that is incremented and then added to a List called "monitor". "cnt" is incremented by multiple threads, and values are added to "monitor" by multiple threads.
At the end of the method "go()", cnt and monitor.size() should have the same value, but they don't. monitor.size() does have the correct value.
If you change the code by uncommenting one of the commented synchronized blocks, and commenting out the currently uncommented one, the code produces the expected results. Also, if you set the thread count (THREAD_COUNT) to 1, the code produces the expected results.
This can only be reproduced on a machine with multiple real cores.
public class ThreadTester {
private List<Integer> monitor = new ArrayList<Integer>();
private Integer cnt = 0;
private static final int NUM_EVENTS = 2313;
private final int THREAD_COUNT = 13;
public ThreadTester() {
}
public void go() {
Runnable r = new Runnable() {
#Override
public void run() {
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
// synchronized(cnt) {
// cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
// }
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
// synchronized(cnt) {
// cnt += NUM_EVENTS; // <-- moving the synchronized block here results in the correct value for cnt, no surprise
// }
}
};
Thread[] threads = new Thread[THREAD_COUNT];
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii] = new Thread(r);
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii].start();
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
try { threads[ii].join(); } catch (InterruptedException e) { }
}
System.out.println("Both values should be: " + NUM_EVENTS*THREAD_COUNT);
synchronized (monitor) {
System.out.println("monitor.size() " + monitor.size());
}
synchronized (cnt) {
System.out.println("cnt " + cnt);
}
}
public static void main(String[] args) {
ThreadTester t = new ThreadTester();
t.go();
System.out.println("DONE");
}
}
Ok let's have a look at the different possibilities you mention:
1.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
}
}
First the monitor object is shared between the threads, therefore getting a lock on it (that is what synchronized does) will make sure that the code inside of the block will only be executed by one thread at a time. So the 2 synchronized inside of the outer one are not necessary, the code is protected anyway.
2.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
Ok this one is a little bit tricky. cnt is an Integer object and Java does not allow modifying an Integer object (Integers are immutable) even though the code suggests that this is what is happening here. But what acutally will happen is that cnt++ will create a new Integer with the value cnt + 1 and override cnt.
This is what the code actually does:
synchronized(cnt) {
Integer tmp = new Integer(cnt + 1);
cnt = tmp;
}
The problem is that while one thread will create a new cnt object while all other threads are waiting to get a lock on the old one. The thread now releases the old cnt and will then try to get a lock on the new cnt object and get it while another thread gets a lock on the old cnt object. Suddenly 2 threads are in the critical section, executing the same code and causing a race condition. This is where the wrong results come from.
If you remove the first synchronized block (the one with monitor), then your result gets even more wrong because the chances of a race increase.
In general you should try to use synchronized only on final variables to prevent this from happening.
I have a class here that will be used as a thread/Runnable object, the second class below (UseSearch) has a main method that intantiates two instances of the Search class and uses them to create two threads. As you can see, the run method calls the add method that runs the loop depending on the direction passed in. I am looking for a mechanism that will cause one of the threads to stop the other thread's loop from iterating when the other thread has finished running it's iteration. Any help/advise will be highly appreciated. I have seen a similar example but it's far too complex for me to comprehend. - Jevison7x
public class Search implements Runnable
{
int sum;
boolean direction;
String name;
public Search(String n, boolean positive)
{
this.direction = positive;
this.name = n;
}
void add()
{
if(direction == true)
{
for(int i = 0; i < 100; i++)
{
sum += 1;
System.out.println(name+" has "+sum);
}
}
else
{
for(int i = 0; i < 100; i++)
{
sum -= 1;
System.out.println(name+" has "+sum);
}
}
}
public void run()
{
add();
}
}
public class UseSearch
{
public static void main(String[] args)
{
Search s1 = new Search("bob", true);
Search s2 = new Search("dan", false);
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s2);
t1.start();
t2.start();
}
}
The thread that is doing the iterating needs to test something on each iteration to see if it has been told to stop. That could be a custom flag (implemented in a variety of ways) or a the thread's interrupted flag.
If you are going to use interrupt, then Matt Clark's answer is half of the picture. The other half is that the iterating thread needs to do something like this:
if (Thread.currentThread.isInterrupted()) {
// pause or stop or break out of the loop or whatever
}
... in the body of the relevant loop or loops.
Note: there is no safe way in Java to stop or pause another thread that is not regularly checking to see if it should stop / pause; i.e. a thread that is not cooperating.
Long answer short...
Make the Threads class-wide variables so that each thread has access to the other:
Thread t1, t2;
public static void main(String[] args){
t1 = new Thread(){
public void run(){
t2.interrupt();
}
};
t2=new Thread(){
public void run(){
t1.interrupt();
}
};
}
I have a thread with the following form:
each execution of each thread is supposed to run a function in the class. That function is completely safe to run by itself. The function returns a value, say an int.
After all threads have been executed, the function values need to be accumulated.
So, it goes (in pseudo-code) something like that:
a = 0
for each i between 1 to N
spawn a thread independently and call the command v = f(i)
when thread finishes, do safely: a = a + v
end
I am not sure how to use Java in that case.
The problem is not creating the thread, I know this can be done using
new Thread() {
public void run() {
...
}
}
the problem is accumulating all the answers.
Thanks for any info.
I would probably do something like:
public class Main {
int a = 0;
int[] values;
int[] results;
public Main() {
// Init values array
results = new int[N];
}
public int doStuff() {
LinkedList<Thread> threads = new LinkedList<Thread>();
for (final int i : values) {
Thread t = new Thread() {
public void run() {
accumulate(foo(i));
}
};
threads.add(t);
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
// Act accordingly, maybe ignore?
}
}
return a;
}
synchronized void accumulate(int v) {
// Synchronized because a += v is actually
// tmp = a + v;
// a = tmp;
// which can cause a race condition AFAIK
a += v;
}
}
Use an ExecutorCompletionService, Executor, and Callable.:
Start with a Callable that calls your int function:
public class MyCallable implements Callable<Integer> {
private final int i;
public MyCallable(int i) {
this.i = i;
}
public Integer call() {
return Integer.valueOf(myFunction(i));
}
}
Create an Executor:
private final Executor executor = Executors.newFixedThreadPool(10);
10 is the maximum number of threads to execute at once.
Then wrap it in an ExecutorCompletionService and submit your jobs:
CompletionService<Integer> compService = new ExecutionCompletionService<Integer>(executor);
// Make sure to track the number of jobs you submit
int jobCount;
for (int i = 0; i < n; i++) {
compService.submit(new MyCallable(i));
jobCount++;
}
// Get the results
int a = 0;
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
}
ExecutorCompletionService allows you to pull tasks off of a queue as they complete. This is a little different from joining threads. Although the overall outcome is the same, if you want to update a UI as the threads complete, you won't know what order the threads are going to complete using a join. That last for loop could be like this:
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
updateUi(a);
}
And this will update the UI as tasks complete. Using a Thread.join won't necessarily do this since you'll be getting the results in the order that you call the joins, not the order that the threads complete.
Through the use of the executor, this will also allow you to limit the number of simultaneous jobs you're running at a given time so you don't accidentally thread-bomb your system.