Concurrency in java - java

public class MyTest {
ArrayList<Integer> array = new ArrayList<>();
public void initialize() {
//....
}
private void editArray(int num) {
// modified the array
}
public void func(int n) {
for (int i = 0; i < n; i++) {
editArray(i);
}
}
}
I hope to execute "editArray" function in the forloop concurrently, which means n threads(call editArray function) can execute concurrently, how can I do that and add a lock for ArrayList array ? I google a lot, most of tutorials just teach how to spawn thread for different objects. What I want is that spawn thread in a single object.
I mainly want to know how to call a function concurrently in java.
Thanks.

Related

Is this concurrent code slower because of overhead? or is something else at play?

I'm playing around with trying to build a arraylist class that is made threadsafe in a very clumsy way by just slapping on the synchronized keyword on all methods
import java.util.stream.*;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class LongArrayListUnsafe {
public static void main(String[] args) {
LongArrayList dal1 = LongArrayList.withElements();
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (int i=0; i<1000; i++) {
executorService.execute(new Runnable() {
public void run() {
for (int i=0; i<10; i++)
dal1.add(i);
}
});}
System.out.println("Using toString(): " + dal1);
for (int i=0; i<dal1.size(); i++)
System.out.println(dal1.get(i));
System.out.println(dal1.size());} }
class LongArrayList {
private long[] items;
private int size;
public LongArrayList() {
reset();
}
synchronized public static LongArrayList withElements(long... initialValues){
LongArrayList list = new LongArrayList();
for (long l : initialValues) list.add( l );
return list;
}
// reset me to initial
synchronized public void reset(){
items = new long[2];
size = 0;
}
// Number of items in the double list
synchronized public int size() {
return size;
}
// Return item number i
synchronized public long get(int i) {
if (0 <= i && i < size)
return items[i];
else
throw new IndexOutOfBoundsException(String.valueOf(i));
}
// Replace item number i, if any, with x
synchronized public long set(int i, long x) {
if (0 <= i && i < size) {
long old = items[i];
items[i] = x;
return old;
} else
throw new IndexOutOfBoundsException(String.valueOf(i));}
// Add item x to end of list
synchronized public LongArrayList add(long x) {
if (size == items.length) {
long[] newItems = new long[items.length * 2];
for (int i=0; i<items.length; i++)
newItems[i] = items[i];
items = newItems;
}
items[size] = x;
size++;
return this;
}
synchronized public String toString() {
return Arrays.stream(items, 0,size)
.mapToObj( Long::toString )
.collect(Collectors.joining(", ", "[", "]"));
}
}
The relevant thing I'm doing is adding a bunch elements to a list, with some tasks. The issue is that when I increase the amount of threads that I pass to the fixedthreadPool, my code runs in the same time as when I only pass only one thread, maybe even slower.
I have three theories on why this is:
This is because of thread overhead, and the tasks I am creating are simply too small, I need to make them bigger before it pays off to use more threads.
It has to do with lock contention, because my class is so clumsily threadsafe, the threads a are competing for the locks, and somehow slowing down everything
I'm making a completely obvious mistake in using the threadexecutorpool
It is not only that your task is to simple. The key issue is that you marked the add function is synchronized which means that only a single thread is allowed to enter this function. No matter how many executers you use, at any single point in time, there is only one thread executing this function, while the others have to wait. Even if you make the task more complex, it won't change. You need to have a more complex task and a more fine grained synchronization thereof.
As for lock contention. Yes, see above, and of course acquiring and releasing locks costs time.
To answer the question in the comments:
sychronized synchronizes on the object on which you invoke the class, (i.e., dal1 which is shared by all your threads).
yes, the contention is fairly obvious. You said yourself "just slapping". Nevertheless for the code you have I would call it adequate. The operation that takes the longest is resizing and copying of the array and during that time you certainly do not want any other thread to modify your array.

QuickSort visualisation via java swing

I wanted to make some kind of sorting algorithms visualisation is java swing but I am stuck on quicksort since I need to stop the partition loop every iteration so the array can redraw. That's how I wanted to do it but without any success
public int partition(int lowIndex, int highIndex,int i)
{
int pivot = highIndex;
for(int j=lowIndex; j<highIndex; j++)
{
if(isBigger(j,pivot))
{
i++;
swap(i,j);
return i;
}
}
swap(i+1,pivot);
return i+1;
}
Didn't find any good solution to keep track on i as well. I'm just clueless
Google for "Java swing visualize sorting algorithms" and you'll find many hits.
For example:
Code Review: sorting algorithm visualization program
Key points:
You need to modify your "sort" code to trigger some kind of "event" at each step (e.g. every time you swap elements):
EXAMPLE:
public class BubbleSort implements SortingAlgorithm {
...
#Override
public void doSort(int[] nums) {
...
SortingAlgorithm.setCurrentBar(j+1);
SortingAlgorithm.sleepFor(delay);
The "event handler" will redraw the array (or, more accurately, request the Event Dispatcher thread (EDT) to repaint).
Consequently, the event handler needs to "know about" the array, and the current index
EXAMPLE:
public abstract interface SortingAlgorithm {
...
public abstract void doSort(int[] nums);
public abstract void changeDelay(int delay);
public static void setCurrentBar(int currentBarIndex) {
PaintSurface.currentBarIndex = currentBarIndex;
}
...
There also needs to be some kind of "delay" between each step
This example uses SwingUtilities.invokeLater(). The example camickr suggests SwingWorker.
I hope that gives you a few ideas, and points you in the right direction!
Instead of calling partition from other class I implemented partition() and sort() methods in an anonymous SwingWorker class and after every swap in partition() method I called publish(array). Uploading source code if anyone would like to see how I solved this problem or would need help himself. Any feedback is really appreciate since it's my first "bigger" project
private void startThread()
{
SwingWorker sw1 = new SwingWorker() {
public int partition(int lowIndex, int highIndex) {
int pivot = highIndex;
int i = lowIndex - 1;
for (int j = lowIndex; j < highIndex; j++) {
if (sorter.isBigger(pivot, j)) {
i++;
sorter.swap(i, j);
try {
Thread.sleep(100);
}
catch(Exception e)
{
// not implemented yet
}
publish(sorter.getArray());
}
}
sorter.swap(i+1,pivot);
publish(sorter.getArray());
return i+1;
}
public void sort(int lowIndex, int highIndex)
{
if(lowIndex < highIndex)
{
int i = partition(lowIndex,highIndex);
try{
sort(lowIndex,i-1) ;
}
finally {
sort(i+1, highIndex);
}
}
}
#Override
protected int[] doInBackground() throws Exception {
sorter.setArray(drafter.getArray());
while (!sorter.isArraySorted()) {
//Thread.sleep(10);
sort(0,sorter.getLength()-1);
}
return sorter.getArray();
}
protected void process(List chunks)
{
int[] val = (int[]) chunks.get(chunks.size()-1);
drafter.ChangeArray(val);
//drafter.repaint();
}
};
sw1.execute();
}

Java WordCounter

Hello I have a project for school where I must create a program in java that counts the words in one or more files. It should start a new thread for each new file. Its also supposed to have locks to protect the combined word counter and a counter for active threads. Ive tried researching locks, but im having trouble grasping the concept.
Here is what I was able to come up with so far.
public class Main {
public static void main(String[] args)throws InterruptedException {
WordCount[] counters = new WordCount[args.length];
for (int index = 0; index < args.length; ++index)
{
counters[index] = new WordCount(args[index]);
counters[index].start();
}
int total = 0;
for (WordCount counter : counters)
{
counter.join();
total += counter.count;
}
System.out.println("Total:" + total);
}
}
public class WordCount extends Thread {
int count;
#Override
public void run()
{
count = 0; //it will count the words
++count;
}
}
'Protecting' the word counter really just means preventing two threads from attempting to update the word counter at the same time. The simplest way to achieve that in Java is with the synchronized keyword:
class WordCounter {
private int count = 0;
public synchronized void incrementCount() {
count++;
}
}
Now if two threads call that method the JVM will force one to wait until the other completes.
Next you need a method that will count words in a file. That should be relatively simple. Something like:
private void countWords(Path path) {
for (String line : Files.readAllLines(path)) {
for (String word : line.split("\\s+")) {
counter.incrementCount();
}
}
}
You'll need to cope with IO exceptions here.
Finally you need to create a thread for each file. At the moment you are subclassing the Thread class but a simpler solution is just to create a thread with the Runnable you need the thread to run:
for (Path path: myFiles) {
Thread thread = new Thread(() -> counter.countWords(path));
thread.run();
}
That's about it. I haven't added the code to keep a running thread count but it really just follows the same pattern.

Java Synchronization Trouble [duplicate]

This question already has answers here:
Synchronization on immutable objects (in java)
(4 answers)
Closed 6 years ago.
I'm new to java and was trying out synchronization with a sample program to add numbers upto 100 using multiThreading. And following is code i was able to come up with. When i test the code it sometimes gives the correct value of 4590 but sometimes doesnt give the correct value. Can anyone point out what i'm doing wrong
class Counter{
Integer counter = 0;
public void increment(int i){
synchronized (counter){
counter += i;
}
}
}
class ObjectTest implements Runnable{
int i;
Counter blah;
public ObjectTest(Counter counter,int i){
blah =counter;
this.i = i;
}
#Override
public void run() {
blah.increment(i);
}
}
public class SyncTest {
public static void main(String args[]) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(4,10,60, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());
Counter counter = new Counter();
for (int index = 0; index < 100; index++) {
ObjectTest objectTest = new ObjectTest(counter,index);
executor.execute(objectTest);
}
executor.shutdown();
while (!executor.isTerminated()){
Thread.sleep(1000L);
}
System.out.println(counter.counter);
}
}
You can't synchronize on counter because it's an Integer, which is immutable. Therefore counter += i creates a new Integer object, which is not the same that was synchronized on.
You can make it int counter and have a separate Object lock = new Object();, synchronizing on lock.

Multi threads in Java

I have some class. For example:
public class Data {
private String name;
public Data(String url) {
// There is download something from the Internet and set field "name".
}
public String getName() {
return name;
}
}
In some method I need to initialize array of objects Data.
ArrayList<Data> list = new ArrayList<Data>;
for(int i=0; i<max; i++) {
list.add(new Data("http://localhost/" + String.valueOf(i)));
}
But it is to long. I wanna do this:
final ArrayList<Data> list = new ArrayList<Data>;
for(int i=0; i<max; i++) {
final int tmp = i;
new Thread() {
public void run() {
list.add(new Data("http://localhost/" + String.valueOf(tmp)));
}
}.start();
}
But the main thread ends sooner than the others and variable list is empty. What should I do? Help pls :)
UP. That is not too fast to download some data from the Internet that's why I've created several threads.
Instead of dealing with the low level details of the Thread API, you could use the java concurrent package, with an executor to handle the threads (I don't know what ListArray is but if it is not thread safe you will have issues with the solution proposed some of the other answers: adding a join will not be sufficient).
For example, a simplified example would be:
final ExecutorService executor = Executors.newFixedThreadPool(10);
final List<Future<Data>> list = new ArrayList<Future<Data>>(max);
for (int i = 0; i < max; i++) {
final int tmp = i;
Callable<Data> c = new Callable<Data>() {
#Override
public Data call() {
return new Data("http://localhost/" + tmp);
}
};
list.add(executor.submit(c));
}
executor.shutdown();
for (Future<Data> future : list) {
Data data = future.get(); //will block until the page has been downloaded
//use the data
}
Ideally, you whould add some error handling around future.get(), as it will throw an ExecutionException if your task throws an exception, which I suppose could happen if the page is not availble for example.
1. When you fire the Another thread, that does the work of getting the data from net and populating the list, immediately after that use join() method.
2. join() method will not let the next line to execute before the run() method of the thread on which it is called has finish().
3. So your main() method will not be executed before the list is populated as you have used join() to hold the execution before the other thread is done.....
In your main use Thread.join to wait for the child threads to complete
Thread[] threads = new Thread[max];
final List<Data> list = Collections.synchronizedList(new ArrayList<Data>());
for(int i=0; i< max; i++) {
final int tmp = i;
Thread t = new Thread() {
public void run() {
list.add(new Data("http://localhost/" + String.valueOf(tmp)));
}
};
t.start();
threads[i] = t;
}
for (Thread t : threads) {
t.join();
}

Categories