Currently when I run the program, the threads are running at random. For example the current output is :
Global.sharedBuffer[0] = 2
Global.sharedBuffer[1] = 1
Global.sharedBuffer[2] = 1
Global.sharedBuffer[3] = 1
Global.sharedBuffer[4] = 1
Global.sharedBuffer[5] = 1
Global.sharedBuffer[6] = 1
Global.sharedBuffer[7] = 1
Global.sharedBuffer[8] = 1
Global.sharedBuffer[9] = 1
Global.sharedBuffer[10] = 2
Global.sharedBuffer[11] = 4
Global.sharedBuffer[12] = 3
What I want is from sharedBuffer 0 to 9 all 1's , then from 10 - 19 all 2's and etc. I added a synchronization block thinking it would do this, however, it just stopped it from context switching every time a thread was called. How do you go about implementing this?
CODE:
import java.io.*;
import java.lang.*;
import java.util.*;
class MyThreadExample2 {
public static void main(String[] args) {
HelloThread ht1 = new HelloThread(1);
HelloThread ht2 = new HelloThread(2);
HelloThread ht3 = new HelloThread(3);
HelloThread ht4 = new HelloThread(4);
ht1.start();
ht2.start();
ht3.start();
ht4.start();
}
}
class Global {
public static int[] sharedBuffer = new int[1000];
public static int in = 0;
}
class HelloThread extends Thread {
int threadID;
HelloThread(int threadID) {
System.out.println("threadID: " + threadID);
this.threadID = threadID;
}
public synchronized void run() {
for (int i = 0; i < 100; i++) {
if((Global.in >= 0 || Global.in <= 99) && (this.threadID == 1))
Global.sharedBuffer[Global.in] = this.threadID;
else if((Global.in >= 100 || Global.in <= 199) && (this.threadID == 2))
Global.sharedBuffer[Global.in] = this.threadID;
else if((Global.in >= 200 || Global.in <= 299) && (this.threadID == 3))
Global.sharedBuffer[Global.in] = this.threadID;
else if((Global.in >= 300 || Global.in <= 399) && (this.threadID == 4))
Global.sharedBuffer[Global.in] = this.threadID;
System.out.println("Thread " + this.threadID + " has written "
+ this.threadID + " to Global.sharedBuffer[" + Global.in + "]\n");
Global.in++;
}
if (this.threadID == 4)
{
try {this.sleep(2000L);
}
catch (Throwable e) {e.printStackTrace();
}
System.out.println("The final buffer is **************\n");
for (int i = 0; i < 30; i++) {
System.out.println("Global.sharedBuffer[" + i + "] = " +
Global.sharedBuffer[i]);
} // for
} // if
} // run
} // end Thread
Multi-threading only works if you can formulate tasks which can be performed independently of others. You have to avoid shared variables and if you can’t avoid it, the access must be properly guarded, which usually implies limiting the concurrency of the thread execution.
For your task it is simple to formulate independent tasks as each thread shall write into a different region of the array:
public class ThreadingExample {
public static void main(String[] args) {
final int numThread=4, chunkSize=10;
int[] array=new int[numThread*chunkSize];
Thread[] thread=new Thread[numThread];
// create threads and define their jobs
for(int t=0, p=0; t<numThread; t++, p+=chunkSize) {
thread[t]=new Thread(new FillInJob(array, t, p, chunkSize));
}
// start the threads
for(Thread t: thread) t.start();
// now all running concurrently
// wait for completion
try {
for(Thread t: thread) t.join();
} catch(InterruptedException ex) {
throw new AssertionError(ex);
}
// use result
System.out.println(java.util.Arrays.toString(array));
}
}
class FillInJob implements Runnable {
private final int[] targetArray;
private final int myID, startIndex, endIndex;
FillInJob(int[] target, int id, int start, int size) {
targetArray=target;
myID=id;
startIndex=start;
endIndex=start+size;
}
public void run() {
for(int ix=startIndex; ix<endIndex; ix++)
targetArray[ix]=myID;
}
}
Related
I want fibonacci series to be printed by threads and the 1st number of the series should be printed by 1st thread then 2nd number by 2nd thread then 3rd by 1st thread and 4th by 2nd and so on.
I tried this code by using arrays like printing the array elements using thread but I am not able to switch between the threads.
class Fibonacci{
void printFibonacci() {
int fibArray[] = new int[10];
int a = 0;
int b = 1;
fibArray[0] = a;
fibArray[1] = b;
int c;
for(int i=2;i<10;i++) {
c = a+b;
fibArray[i] = c;
a = b;
b = c;
}
for(int i=0;i<10;i++) {
if(Integer.parseInt(Thread.currentThread().getName())%2==0 && (i%2==0))
{
System.out.println("Thread " +Thread.currentThread().getName()+" "+fibArray[i]);
try{
wait();
}catch(Exception e) {}
}
else if(Integer.parseInt(Thread.currentThread().getName())%2!=0 && (i%2!=0))
{
System.out.println("Thread " +Thread.currentThread().getName()+" "+fibArray[i]);
}
}
}
}
public class FibonacciUsingThread {
public static void main(String[] args) throws Exception {
Fibonacci f = new Fibonacci();
Thread t1 = new Thread(()->
{
f.printFibonacci();
});
Thread t2 = new Thread(()->
{
f.printFibonacci();
});
t1.setName("0");
t2.setName("1");
t1.start();
t1.join();
t2.start();
}
}
The following line in your code is causing t1 to finish before t2 can start.
t1.join();
Apart from this, you need to synchronize on the method, printFibonacci.
You can do it as follows:
class Fibonacci {
synchronized void printFibonacci() throws InterruptedException {
int fibArray[] = new int[10];
int a = 0;
int b = 1;
fibArray[0] = a;
fibArray[1] = b;
int c;
for (int i = 2; i < 10; i++) {
c = a + b;
fibArray[i] = c;
a = b;
b = c;
}
for (int i = 0; i < 10; i++) {
String currentThreadName = Thread.currentThread().getName();
if (currentThreadName.equals("1")) {
if (i % 2 == 0) {
System.out.println("Thread " + Thread.currentThread().getName() + " " + fibArray[i]);
notify();
} else {
wait();
}
} else if (currentThreadName.equals("0")) {
if (i % 2 == 1) {
System.out.println("Thread " + Thread.currentThread().getName() + " " + fibArray[i]);
notify();
} else {
wait();
}
}
}
}
}
public class Main {
public static void main(String[] args) {
Fibonacci f = new Fibonacci();
Thread t1 = new Thread(() -> {
try {
f.printFibonacci();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
f.printFibonacci();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.setName("0");
t2.setName("1");
t1.start();
t2.start();
}
}
Output:
Thread 1 0
Thread 0 1
Thread 1 1
Thread 0 2
Thread 1 3
Thread 0 5
Thread 1 8
Thread 0 13
Thread 1 21
Thread 0 34
Apart from all being said and already answered, I would just like to add one alternative approach to Fibonacci sequence implemetation, without arrays and in-advance dimensioning:
public class Fibonacci {
private int index = -1;
private int previous = 0;
private int last = 1;
synchronized public int getNext() {
index++;
if( index == 0 ) return previous;
if( index == 1 ) return last;
int next = last + previous;
if( next < 0 ) throw new ArithmeticException( "integer overflow" );
previous = last;
last = next;
return next;
}
}
Limited only by overflow of numeric data type, in this case integer.
As "#Live and Let Live" pointed out, correctness-wise the main issues with your code is the missing synchronized clause and calling join of the first thread before starting the second thread.
IMO you could clean the code a bit by first separating a bite the concerns, namely, the class Fibonacci would only responsible for calculation the Fibonacci of a given array:
class Fibonacci{
void getFibonacci(int[] fibArray) {
int a = 0;
int b = 1;
fibArray[0] = a;
fibArray[1] = b;
int c;
for(int i=2;i<fibArray.length;i++) {
c = a+b;
fibArray[i] = c;
a = b;
b = c;
}
}
}
In this way, you keep your Fibonacci class concise without any thread-related code. Moreover, the getFibonacci is now more abstract; you can calculate the fib of more than just 10 elements like you had before.
Then on the class FibonacciUsingThread:
public class FibonacciUsingThread {
public static void main(String[] args) throws Exception {
int [] array_fib = new int[10];
Fibonacci f = new Fibonacci();
f.getFibonacci(array_fib);
Thread t1 = new Thread(()->
{
for(int i = 0; i < array_fib.length; i+=2)
System.out.println("Thread 1:" + array_fib[i]);
});
Thread t2 = new Thread(()->
{
for(int i = 1; i < array_fib.length; i+=2)
System.out.println("Thread 2:" + array_fib[i]);
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
First, you calculate the Fibonaccis using the main thread, there is no point in having all the threads calculate the same thing. Afterward, you specified that Thread 1 and Thread 2 will print the even and odd positions, respectively.
Unless this is just an exercise to play around with threads and synchronization there is not much sense in using threads to do this kind of work. In your code, the part worth parallelizing is the calculation of the Fibonacci numbers themselves, not the printing part.
The code previously shown will not print the Fibonacci numbers in order, for that you need to ensure that the threads wait for one another after iterating through each element of the array. Hence, you need to adapt the code that will be executed by the threads, namely:
Thread t1 = new Thread(()->
{
synchronized (array_fib){
for(int i = 0; i < array_fib.length; i++)
if(i % 2 == 0) {
System.out.println("Thread 1:" + array_fib[i]);
try {
array_fib.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
array_fib.notify();
}
});
Thread t2 = new Thread(()->
{
synchronized (array_fib){
for(int i = 0; i < array_fib.length; i++)
if(i % 2 != 0) {
System.out.println("Thread 2:" + array_fib[i]);
try {
array_fib.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
array_fib.notify();
}
});
We can remove the code redundancy by extracting a method with the work that will be assigned to the Threads. For instance:
private static void printFib(String threadName, int[] array_fib, Predicate<Integer> predicate) {
for (int i = 0; i < array_fib.length; i++)
if (predicate.test(i)) {
System.out.println(threadName + " : " + array_fib[i]);
try {
array_fib.wait();
} catch (InterruptedException e) {
// do something about it
}
} else
array_fib.notify();
}
and the main code:
public static void main(String[] args) throws Exception{
int [] array_fib = new int[10];
Fibonacci f = new Fibonacci();
f.getFibonacci(array_fib);
Thread t1 = new Thread(()-> {
synchronized (array_fib){
printFib("Thread 1:", array_fib, i1 -> i1 % 2 == 0);
}
});
Thread t2 = new Thread(()-> {
synchronized (array_fib){
printFib("Thread 2:", array_fib, i1 -> i1 % 2 != 0);
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
As an alternative, you can use a fair Semaphore to alternate between threads, and an AtomicReference to keep the shared status. Here's an example:
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;
public class FibonacciConcurrent {
public static void main(String[] args) throws InterruptedException {
// needs to be fair to alternate between threads
Semaphore semaphore = new Semaphore(1, true);
// set previous to 1 so that 2nd fibonacci number is correctly calculated to be 0+1=1
Status initialStatus = new Status(1, 0, 1);
AtomicReference<Status> statusRef = new AtomicReference<>(initialStatus);
Fibonacci fibonacci = new Fibonacci(20, semaphore, statusRef);
Thread thread1 = new Thread(fibonacci);
Thread thread2 = new Thread(fibonacci);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
private static final class Status {
private final long previous;
private final long current;
private final int currentIndex;
private Status(long previous, long current, int currentIndex) {
this.previous = previous;
this.current = current;
this.currentIndex = currentIndex;
}
}
private static final class Fibonacci implements Runnable {
private final int target;
private final Semaphore semaphore;
private final AtomicReference<Status> statusRef;
private Fibonacci(int target, Semaphore semaphore, AtomicReference<Status> statusRef) {
this.target = target;
this.semaphore = semaphore;
this.statusRef = statusRef;
}
#Override
public void run() {
try {
process();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted", e);
}
}
private void process() throws InterruptedException {
while (!Thread.currentThread().isInterrupted()) {
try {
semaphore.acquire();
Status status = statusRef.get();
String threadName = Thread.currentThread().getName();
if (status.currentIndex > target) return;
System.out.println(
threadName + ": fibonacci number #" + status.currentIndex + " - " + status.current);
long next = status.previous + status.current;
Status newStatus = new Status(status.current, next, status.currentIndex + 1);
statusRef.set(newStatus);
} finally {
semaphore.release();
}
}
}
}
}
Will print:
Thread-0: fibonacci number #1 - 0
Thread-1: fibonacci number #2 - 1
Thread-0: fibonacci number #3 - 1
Thread-1: fibonacci number #4 - 2
Thread-0: fibonacci number #5 - 3
Note that this solution does not only print on the threads - it does the actual calculation on the threads as well - e.g. when it's Thread A's turn, it uses the previous status that was calculated by Thread B to calculate the next fibonacci number.
all
I'm trying to check multithread processing of the some data set that contain number from 1 to N. For example, I want to sum all this number:
1) Hold the sum (result).
public class ResultHolder {
public static AtomicLong total_time = new AtomicLong(0);
public static Long sum = 0l;
public Long getSum() {
return sum;
} // END: getSum()
#PostConstruct
public void init() {
} // END: init()
public void setSum(Long sum) {
this.sum = sum;
} // END: setSum()
public void printSum() {
System.out.println("Sum is " + sum);
}
public void clearSum() {
sum = 0l;
}
} // ENDC: ResultHolder
2) Process part of number's set:
public class SumProcessor {
private static int global_id = 0;
final public int processor_id;
private final ArrayList<Long> numbers;
private Long processor_sum = 0l;
#Autowired
private final ResultHolder sumHoldder = null;
public SumProcessor(ArrayList<Long> numbers) {
this.numbers = numbers;
processor_id = ++global_id;
} // END: constructor
public void work() throws Exception {
long t1 = new java.util.Date().getTime();
int i = 0;
try {
if (numbers == null) throw new Exception("Не удалось получить массив чисел.");
for (i = 0; i < numbers.size(); i++) {
Long o = null;
try {
o = numbers.get(i);
if (o == null) throw new Exception("no number");
} catch (Exception e) {
throw new Exception("Ошибка извлечения числа из массива: " + e);
}
processor_sum += o;
} // END: for
if (sumHoldder == null) throw new Exception("No sum holder");
synchronized (sumHoldder) {
sumHoldder.setSum(sumHoldder.getSum() + processor_sum);
}
long t2 = new java.util.Date().getTime();
this.sumHoldder.total_time.addAndGet(t2 - t1);
} catch (Exception e) {
System.out.println("Work() error (" + i + ") " + e);
}
return;
} //END: method1
#PostConstruct
public void init() {
System.out.println("Initializated B: " + this);
} //END: method2
#PreDestroy
public void destroy() {
System.out.println("Destroy B: " + this);
} //END: method3
#Override
public String toString() {
return "" +
"Processor " + processor_id + " " +
"contain " + numbers.size() + " " +
"numbers from " + numbers.get(0) +
" to " + numbers.get(numbers.size() - 1);
} //END: toString()
} //END: class SumProcessor
3) Very simple profiler (calcs processing time)
#Aspect
public class MethodLoggerBasic {
#Pointcut("execution(* *.work(..))")
void around_work() {};
#Around("around_work()")
public void logMethodName(ProceedingJoinPoint joinPoint) throws Throwable {
long starttime = new Date().getTime();
joinPoint.proceed();
long endtime = new Date().getTime();
long time = endtime - starttime;
MainApp.time += time;
} // END:
} // ENDC
4) Main program (can start processing linear or in parallel)
public class MainApp {
static AnnotationConfigApplicationContext context;
public static long time = 0l;
public final static int SIZE = 40_000_000;
public final static int DIVIDE_FACTOR = 4;
public static ArrayList<Long>[] numbers = new ArrayList[DIVIDE_FACTOR];
public static ArrayList<SumProcessor> processors = new ArrayList<>();
public static void main(String[] args) throws Exception {
context = new AnnotationConfigApplicationContext(myConfig.class);
// form 4 datasets
int part_size = SIZE / DIVIDE_FACTOR;
int i;
int j;
for (j = 0; j < DIVIDE_FACTOR; j++) {
numbers[j] = new ArrayList<>();
for (i = 0; i < (int) part_size; i++) {
numbers[j].add(((j * part_size) + i + 1l));
}
}
// create 4 processors (bean)
for (i = 0; i < DIVIDE_FACTOR; i++) {
SumProcessor bean = context.getBean(SumProcessor.class, numbers[i]);
if (bean == null) throw new Exception("Error recive bean SumProcessor.class");
processors.add(bean);
}
// creates 4 threads fro processors
thread_process thread1 = new thread_process();
thread_process thread2 = new thread_process();
thread_process thread3 = new thread_process();
thread_process thread4 = new thread_process();
ResultHolder a;
a = context.getBean(ResultHolder.class);
try {
boolean isByPool = true; // flag
time = 0;
if (isByPool) {
System.out.println("-------------------");
System.out.println("Multithread compute");
System.out.println("-------------------");
ExecutorService pool = new ThreadPoolExecutor(
4,
4,
0,
TimeUnit.MICROSECONDS,
new ArrayBlockingQueue<>(4)
);
List<Callable<Boolean>> tasks = new ArrayList();
tasks.add(thread1);
tasks.add(thread2);
tasks.add(thread3);
tasks.add(thread4);
pool.invokeAll(tasks);
pool.shutdown();
pool.awaitTermination(60, TimeUnit.SECONDS);
} else {
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
}
a.printSum();
a.clearSum();
System.out.println("total time is " + a.total_time);
System.out.println("basic time is " + MainApp.time);
System.out.println("-------------");
System.out.println("Single thread");
System.out.println("-------------");
ArrayList<Long> numbers_tolal = new ArrayList<>();
for (i = 0; i < SIZE; i++) {
numbers_tolal.add((i + 1l));
}
SumProcessor sumProcessor = context.getBean(SumProcessor.class, numbers_tolal);
a.total_time.set(0l);
time = 0l;
sumProcessor.work();
a.printSum();
System.out.println("total time is " + a.total_time);
System.out.println("basic time is " + MainApp.time);
} catch (Exception e) {
throw new Exception("MainApp error: " + e);
}
context.close();
} // END: main
} // END: class MainApp
5) Thread process:
public class thread_process extends Thread implements Callable, Runnable {
static int index = 0;
#Override
public void run() {
try {
SumProcessor next = MainApp.processors.get(index++);
if (next == null) {
System.out.println("Нет процессора");
System.exit(-1);
}
next.work();
System.out.println("Thread " + this + " complete!");
} catch (Exception e) {
System.out.println("Error in thread " + this + ": " + e);
}
} //END: run()
#Override
public Boolean call() throws Exception {
run();
return true;
} //END: call()
}; //END: class thread_process
The output is:
Initializated B: Processor 1 contain 10000000 numbers from 1 to 10000000
Initializated B: Processor 2 contain 10000000 numbers from 10000001 to 20000000
Initializated B: Processor 3 contain 10000000 numbers from 20000001 to 30000000
Initializated B: Processor 4 contain 10000000 numbers from 30000001 to 40000000
-------------------
Multithread compute
-------------------
Thread Thread[Thread-3,5,main] complete!
Thread Thread[Thread-4,5,main] complete!
Thread Thread[Thread-2,5,main] complete!
Thread Thread[Thread-1,5,main] complete!
Sum is 800000020000000
total time is 11254
basic time is 11254
-------------
Single thread
-------------
Initializated B: Processor 5 contain 40000000 numbers from 1 to 40000000
Sum is 800000020000000
total time is 6995
basic time is 6995
Is there a method to make it faster in parallel than linear? Or do I perhaps not need to fork this task? Or maybe my profiler is not so good...
GitHub project
You are trying to perform a sequential task using multithreading, that isn't correct use of multithreading. Here, you have a resource for which you need to perform some work. You are using multiple threads to distribute that work, but at the same time, you are blocking one thread when the other thread is using the resource. So, why have worker threads in the first place if you don't want them to access the resource in parallel.
If not necessary, you can drop the Set implementation of the dataset and use List or Arrays where you can access elements using indices without blocking the worker thread.
Update 1: Just add one more line after pool.shutdown() call.
pool.shutdown(); // starts thread shutdown, or force execution of worker threads
pool.awaitTermination(60, TimeUnit.SECONDS); // blocks main thread until thread pool finishes
// ...
// now you can do your single thread task
Also, don't create too many threads since a single thread is fast enough to handle million array elements.
Update 2: So, I don't know why but putting the single thread out of try block seems to get me the expected result.
public class MainApp {static AnnotationConfigApplicationContext context;
public static long time = 0;
public final static int SIZE = 28_000_000;
public final static int DIVIDE_FACTOR = 4;
public static ArrayList<Long>[] numbers = new ArrayList[DIVIDE_FACTOR];
public static ArrayList<SumProcessor> processors = new ArrayList<>();
public static void main(String[] args) throws Exception {
context = new AnnotationConfigApplicationContext(AppConfig.class);
ResultHolder a = context.getBean(ResultHolder.class);
// form 4 datasets
int part_size = SIZE / DIVIDE_FACTOR;
int i;
int j;
for (j = 0; j < DIVIDE_FACTOR; j++) {
numbers[j] = new ArrayList<>(part_size);
for (i = 0; i < (int) part_size; i++) {
numbers[j].add(((j * part_size) + i + 1l));
}
}
// create 4 processors (bean)
for (i = 0; i < DIVIDE_FACTOR; i++) {
SumProcessor bean = context.getBean(SumProcessor.class, numbers[i]);
if (bean == null) throw new Exception("Error receive bean SumProcessor.class");
processors.add(bean);
}
// creates 4 threads fro processors
thread_process thread1 = new thread_process();
thread_process thread2 = new thread_process();
thread_process thread3 = new thread_process();
thread_process thread4 = new thread_process();
try {
boolean isByThread = true; // flag
time = 0;
System.out.println("-------------------");
System.out.println("Multithread compute");
System.out.println("-------------------");
ExecutorService pool = new ThreadPoolExecutor(
4,
4,
0,
TimeUnit.MICROSECONDS,
new LinkedBlockingDeque<>(4) // or ArrayBlockingDeque<>(4)
);
List<Callable<Boolean>> tasks = new ArrayList();
tasks.add(thread1);
tasks.add(thread2);
tasks.add(thread3);
tasks.add(thread4);
List<Future<Boolean>> futures = pool.invokeAll(tasks);
pool.shutdown();
pool.awaitTermination(60, TimeUnit.SECONDS);
System.out.println("Time is: " + time);
a.printSum();
a.clearSum();
time = 0;
} catch (Exception e) {
throw new Exception("MainApp error: " + e);
} // <---- moved single thread out of try block
ArrayList<Long> numbers_total = new ArrayList<>(SIZE);
for (i = 0; i < SIZE; i++) {
numbers_total.add((i + 1l));
}
System.out.println("-------------");
System.out.println("Single thread");
System.out.println("-------------");
SumProcessor sumProcessor = context.getBean(SumProcessor.class, numbers_total);
sumProcessor.work();
System.out.println("Time is: " + time);
a.printSum();
a.clearSum();
time = 0;
context.close();
} // END: main
}
Output:
Initialized B: Processor 1 contain 7000000 numbers from 1 to 7000000
Initialized B: Processor 2 contain 7000000 numbers from 7000001 to 14000000
Initialized B: Processor 3 contain 7000000 numbers from 14000001 to 21000000
Initialized B: Processor 4 contain 7000000 numbers from 21000001 to 28000000
-------------------
Multithread compute
-------------------
Thread[Thread-3,5,main] complete task.
Thread[Thread-2,5,main] complete task.
Thread[Thread-1,5,main] complete task.
Thread[Thread-4,5,main] complete task.
Time is: 5472
Sum is 392000014000000
-------------
Single thread
-------------
Initialized B: Processor 5 contain 28000000 numbers from 1 to 28000000
Time is: 10653
Sum is 392000014000000
Output [Reverse order]:
-------------
Single thread
-------------
Initialized B: Processor 1 contain 28000000 numbers from 1 to 28000000
Time is: 2265
Sum is 392000014000000
Initialized B: Processor 2 contain 7000000 numbers from 1 to 7000000
Initialized B: Processor 3 contain 7000000 numbers from 7000001 to 14000000
Initialized B: Processor 4 contain 7000000 numbers from 14000001 to 21000000
Initialized B: Processor 5 contain 7000000 numbers from 21000001 to 28000000
-------------------
Multithread compute
-------------------
Thread[Thread-2,5,main] complete task.
Thread[Thread-4,5,main] complete task.
Thread[Thread-1,5,main] complete task.
Thread[Thread-3,5,main] complete task.
Time is: 2115
Sum is 392000014000000
I'm trying to build simple multithreading application. But I'm confused about Java monitors. I have many threads that want to format with their data one array. So for example I have Supermarket Threads (data of the thread is in txt file) So first thread have these product (Milk, Cheese, Chocolate) and country code for each product 1,2, 3
SupermarketA
Milk 1
Cheese 2
Chocolate 3
SupermarketB
Yogurt 1
Orangle 2
Bannana 3
Tea 7
Kiwi 9
and I want to format array that has to fields (country_code and count)
So my array should look like that
Country_code count
1 2
2 2
3 2
7 1
9 1
Code
public class SortedArray{
private int num = 0; // num is country code
private int count = 0;
}
So here's my monitor class
public class SingleArray {
private SortedArray[] array;
private int arrayIndex;
private static final int MAX_SIZE = 5;
public SingleArray() {
array = new SortedArray[MAX_SIZE];
arrayIndex = 0;
initArray();
}
private void initArray() {
for (int i = 0; i < MAX_SIZE; i++) {
array[i] = new SortedArray();
}
}
public synchronized void inc(){
awaitUnderMax();
notifyAll();
}
private void awaitUnderMin(){
while (arrayIndex == 0) try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void dec(){
awaitUnderMin();
notifyAll();
}
public void add(ArrayList<Integer> count){
for (int i = 0; i < count.size(); i++) {
singleArray.inc();
int num = count.get(i);
if (singleArray.arrayIndex == 0) { // if array is empty add value to it
singleArray.array[0].num = num;
singleArray.array[0].count++;
singleArray.arrayIndex++;
} else {
if (!isThere(num)) { // if num is a new value to array
singleArray.inc();
int index1 = singleArray.arrayIndex;
if (num > singleArray.array[index1 - 1].num) {
singleArray.inc();
singleArray.array[index1].num = num;
singleArray.inc();
singleArray.array[index1].count++;
singleArray.inc();
singleArray.arrayIndex++;
System.out.println(Thread.currentThread().getName() + " first " + singleArray.array[index1].num);
} else if (num < singleArray.array[index1 - 1].num) { // jei num mazesne uz paskutinia masyvo reiksme
int index = index1 - 1 < 0 ? index1 : index1 - 1;
while (index > 0 && num < singleArray.array[index].num) {
index--;
}
if (index != singleArray.arrayIndex) {
System.out.println(Thread.currentThread().getName() + " sec " + singleArray.array[index].num);
singleArray.array = addPos(singleArray.array, index + 1, num);
}
}
}
}
}
}
public boolean isThere(int number){
for(int i=0; i<singleArray.arrayIndex; i++){
singleArray.inc();
if(number == singleArray.array[i].num){
singleArray.array[i].count++;
return true;
}
}
return false;
}
private void awaitUnderMax(){
while (arrayIndex >= MAX_SIZE) try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void removeValue(int number, int howManyItems){
for(int i=0; i<arrayIndex; i++){
dec();
if(number == array[i].num){
int numberToDelete = array[i].count - howManyItems >= 0 ? howManyItems : array[i].count;
if(array[i].count >= numberToDelete){
array[i].count -= numberToDelete;
}
if(array[i].count == 0){
deleteItem(i);
}
}
if(array[i].count == 0){
deleteItem(i);
}
}
}
Each thread call add(ArrayList<Integer> count) method
So basically what add method does:
Find place where to insert new value (dependng if new value is greater or lower than a previous)
call isThere(int num) method that check if new value is already in array (if so increment count singleArray.array[i].count++) otherwise add new value to array
If array is full arrayIndex == MAX_SIZE wait current thread for other threads to decrement arrayIndex (this is oly one part of code I also have other threads that based on county code decrement array)
So the biggest problem is that multiplethreads need to update single array at the same time (I know that adding synchronized keyword to add method should solve this problem but it only let one thread to run this method at once!) So sometimes all works fine, but sometimes I get really starnge results (for example that country code is 0 (That is imposible!!!) and sometimes new values is placed in wrong array posiitons). Also I think that semaphores should solve this problem, but is it possible to do that with monitors? Thank's for the answers.
EDIT v2
to #Elyasin
public Thread[] setUpShopsBuilderThreads(){
int size = data.getSize();
ArrayList<ArrayList<String>> a = new ArrayList<>();
ArrayList<ArrayList<Integer>> b = new ArrayList<>();
ArrayList<ArrayList<Double>> c = new ArrayList<>();
Thread[] threads = new Thread[size];
for (int i = 0; i < size; i++) {
int tmp = data.getIndex(i);
int range = i + 1 < size ? data.getIndex(i + 1) : data.getWaresSize();
ArrayList<String> name = new ArrayList<>();
ArrayList<Integer> count = new ArrayList<>();
ArrayList<Double> price = new ArrayList<>();
for (int j = tmp; j < range; j++) {
name.add(data.getName(j));
count.add(data.getCount(j));
price.add(data.getPrice(j));
}
a.add(name);
b.add(count);
c.add(price);
}
procesas_1 p1 = new procesas_1(a.get(0), b.get(0), c.get(0));
procesas_2 p2 = new procesas_2(a.get(1), b.get(1), c.get(1));
procesas_3 p3 = new procesas_3(a.get(2), b.get(2), c.get(2));
procesas_4 p4 = new procesas_4(a.get(3), b.get(3), c.get(3));
procesas_5 p5 = new procesas_5(a.get(4), b.get(4), c.get(4));
Thread worker1 = new Thread(p1);
Thread worker2 = new Thread(p2);
Thread worker3 = new Thread(p3);
Thread worker4 = new Thread(p4);
Thread worker5 = new Thread(p5);
threads[0] = worker1;
threads[1] = worker2;
threads[2] = worker3;
threads[3] = worker4;
threads[4] = worker5;
return threads;
}
public static void main(String[] args) {
Starter start = new Starter();
start.read();
start.printShopsData();
start.printUserData();
Thread[] builderThreads = start.setUpShopsBuilderThreads();
for(int i=0; i<builderThreads.length; i++){
builderThreads[i].start();
}
}
what about using the concurrent safe datasets java already provides?
if you want it sorted, this one looks it might work for you:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListSet.html
just add it as in a normal Collection
I have 200 students waiting to enter a room with 200 seats (25 rows and 8 columns). The door capacity is 4 people. When a student enter the room, he chooses random seat (row and column). If the chosen seat is at 9th row or less it takes 1 second to sit, on 18th and less it takes 2 seconds, and if its from 18 to 25 it takes 3 seconds.
When any of them take a seat another person must come in the room.
The problem is that when the first 4 people enter the room they take seat one by one and not at once. How can I fix that?
For example if 2 people choose a seat at 5th row they both need to sit for 1 seconds and two new students must enter the room.
public class Student
{
int row;
int column;
volatile static int mutex;
//Generating random numbers for row and column
public Student(Seats[][] seats)
{
this.row = (int) Math.ceil(Math.random() * 25);
this.column = (int) Math.ceil(Math.random() * 8);
if (!seats[row][column].isTaken)
{
seats[row][column].isTaken = true;
} else
{
do
{
this.row = (int) Math.ceil(Math.random() * 25);
this.column = (int) Math.ceil(Math.random() * 8);
} while (!seats[row][column].isTaken);
seats[row][column].isTaken = true;
}
}
/*Check if the mutex is 4 (4 people are in the room) then wait
if someone enter the room increment mutex*/
synchronized void add() throws InterruptedException
{
while (mutex > 4)
wait();
Student.mutex++;
notifyAll();
}
/* Check if mutex is 0 (no one is in the room) then wait
if the student has sit - decrement mutex and notify*/
synchronized void takeSeat() throws InterruptedException
{
while (mutex == 0)
wait();
Student.mutex--;
notifyAll();
}
}
class Seats
{
int seat;
boolean isTaken;
public Seats(int seat)
{
this.seat = seat;
this.isTaken = false;
}
}
class StudentThread extends Thread
{
Seats[][] seats = new Seats[25][8];
StudentThread(Seats[][] seats)
{
this.seats = seats;
}
public void run()
{
try
{
Student student = new Student(seats);
synchronized (seats)
{
System.out.println("Student enter the room");
/*call the synchronized method from student
that increment the mutex*/
student.add();
if (Student.mutex == 4)
{
if (student.row <= 9)
{
sleep(1000);
student.takeSeat();
System.out.println("Student take a seat at "
+ student.row + " " + student.column);
}
if (student.row <= 18 && student.row > 9)
{
sleep(2000);
student.takeSeat();
System.out.println("Student take a seat at "
+ student.row + " " + student.column);
}
if (student.row <= 25 && student.row > 18)
{
sleep(3000);
student.takeSeat();
System.out.println("Student take a seat at "
+ student.row + " " + student.column);
}
}
}
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
class Main
{
public static void main(String[] args)
{
Seats[][] seats = new Seats[25][8];
//Initializing the seats
for (int i = 0; i < 25; i++)
for (int j = 0; j < 8; j++)
{
seats[i][j] = new Seats(i);
}
for (int i = 0; i < 200; i++)
{
StudentThread T1 = new StudentThread(seats);
T1.start();
}
}
}
Use a Semaphore, they are very practical for these kind of things.
To make the example a bit more realistic: imagine you need to do 200 HTTP get-requests, but the server will ban you if you run more than 4 requests at the same time. The example below shows how you can limit the number of requests running at the same time using a Semaphore.
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class ResourceUsageLimiter {
static ExecutorService executor = Executors.newCachedThreadPool();
static int requests = 20;
static int maxRequestsConcurrent = 4;
static int maxRequestTime = 1000;
static Random randomizer = new Random();
static Semaphore openSlots = new Semaphore(maxRequestsConcurrent);
static long startTime = System.currentTimeMillis();
public static void main(String[] args) {
try {
for (int i = 0; i < requests; i++) {
openSlots.acquire();
executor.execute(new RequestRunner(i));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
static long time() {
return System.currentTimeMillis() - startTime;
}
static class RequestRunner implements Runnable {
int sleepTime, reqId;
public RequestRunner(int reqId) {
this.reqId = reqId;
sleepTime = randomizer.nextInt(maxRequestTime);
}
#Override
public void run() {
try {
System.out.println(time() + " " + reqId + " sleeping " + sleepTime);
Thread.sleep(sleepTime);
System.out.println(time() + " " + reqId + " sleep done");
} catch (Exception e) {
e.printStackTrace();
} finally {
openSlots.release();
}
}
}
}
Ofcourse, another way to limit the maximum number of requests running at the same time in the example is to use a thread pool with a fixed size of 4.
there are 2 part . I am use google app engine java.
1, task Queue, to start 2 process
2, each process using ThreadManager.createThreadForCurrentRequest(new Runnable() {
for 2 Thread
I expect to set the "total_i" value by Thread based on (int i_from, int i_to).
when pass value (1,2) and (3,4) to each Thread, the total of total_i should be 6 and 14.
But the 2 Threads give me the same value 14. I really confused and need help.
Thanks
//part 1 :
total_count = 4; // temp set
record_count= 2;
Queue queue = QueueFactory.getDefaultQueue();
// queue 分段读取 detail data, 每次30个
for (int i = 1; i <= total_count; i += record_count) {
code_from = String.valueOf(i);
code_to = String.valueOf(i + record_count - 1);
queue.add(TaskOptions.Builder.withUrl("/test_DetailDown").method(TaskOptions.Method.GET).param("from", code_from).param("to", code_to));
}
//part 2:
#SuppressWarnings("serial")
public class test_DetailDown extends HttpServlet {
AtomicInteger counter = new AtomicInteger();
final static int ThreadCount = 2;
int[] recordArr = new int[ThreadCount];
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, DeadlineExceededException {
resp.getWriter().println("start");
// this is called by "Queue_Detail_Down" from Queue with parameter : from,
// to
String code_from = req.getParameter("from");
String code_to = req.getParameter("to");
TodayDetail(Integer.valueOf(code_from), Integer.valueOf(code_to));
// process to down data
}
// this is the process to get today datail
private void TodayDetail(int code_from, int code_to) {
int total_i = 0;
// int record_count = 2;
// loop symbol to get detail data from stock.zaobao
for (int i = 0; i < ThreadCount; i++) {
final int i_from = code_from; // pass parameter
final int i_to = code_to;
// thread
Thread thread = ThreadManager.createThreadForCurrentRequest(new Runnable() {
public void run() {
counter.incrementAndGet();
get_detail_data(i_from, i_to); // down web data
counter.decrementAndGet();
}
});
thread.start(); // end thread process
}
// wait all thread
while (true) {
int num = counter.get();
if (num <= 0)
break;
try {
Thread.sleep(300);
} catch (InterruptedException ex) {
}
}
// save data
for (int i = 0; i < ThreadCount; i++) {
total_i = total_i + recordArr[i];
}
System.out.println("after Thread process, total_i =" + total_i);
log("end of program");
}
// core process, get data
private void get_detail_data(int i_from, int i_to) {
for (int i = 0; i < ThreadCount; i++) {
recordArr[i] = i_from + i_to;
}
}
}