I have a Queue containing 10 elements, and I start 100 threads of which 6 may run concurrently, controlled by a Semaphore. When each thread runs, it takes the head element then adds it to the tail. But sometimes I get this exception:
java.util.NoSuchElementException
at java.util.LinkedList.removeFirst(LinkedList.java:270)
at java.util.LinkedList.remove(LinkedList.java:685)
at IBM.SemApp$1.run(SemApp.java:27)
at java.lang.Thread.run(Thread.java:745)
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class SemApp {
public static void main(String[] args) {
Queue queueB = new LinkedList<>();
for (int i = 0; i < 10; i++) {
queueB.add("Object " + i);
}
Runnable limitedCall = new Runnable() {
final Random rand = new Random();
final Semaphore available = new Semaphore(6);
int count = 0;
public void run() {
int time = rand.nextInt(15);
try {
available.acquire();
String A = (String) queueB.remove();
queueB.add(A);
available.release();
count++;
System.out.println(count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(limitedCall).start();
}
}
}
What am I doing wrong?
The problem is that LinkedList is not a thread-safe structure.
Therefore, it should not be shared and modified by multiple concurrent threads as the changes on queueB might not be properly "communicated" to other threads.
Try using a LinkedBlockingQueue instead.
Also, use an AtomicLong for count for the same reason: it is shared in between several threads and you want to avoid race conditions.
The fact that up to six threads may be operating on the queue concurrently means that modifications are not safe.
Related
I have a list and a pointer to an element of the list. From time to time I need to:
append a value at the end of the queue
remove a value from the head of the queue
make the pointer advance to the next value in the list
That is:
from WRITE point of view it's a queue.
from READ point of view it's a list.
If I use a normal Iterator I get ConcurrentModificationException when modifying the queue; if I use a ListIterator I can only remove/add value at the iterator position.
Is there any standard data structure I can use to achieve this?
You can use a ConcurrentLinkedQueue. It allows modifying and iterating at the same time because it includes the necessary mechanisms for synchronization.
The followin snippet shows a working example where there are 3 Threads accessing the same queue without a problem:
1. Iterating and outputting elements
2. Adding new elements once in a while
3. Removing outputted elements once in a while
package test;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class QueueListTest
{
// private static final Queue<Integer> numbers = new ConcurrentLinkedQueue<>();
public static void main(String[] args)
{
final Queue<Integer> numbers = new ConcurrentLinkedQueue<>();
final AtomicInteger insert = new AtomicInteger(0);
final AtomicInteger output = new AtomicInteger();
for(int j = 0; j < 100; j++)
{
numbers.add(insert.getAndIncrement());
}
// print 1 number every 100ms
Thread t1 = new Thread() {
public void run()
{
Iterator<Integer> iter = numbers.iterator();
while(iter.hasNext())
{
int first = numbers.peek();
int size = numbers.size();
int last = first + size - 1;
int current = iter.next();
System.out.println("list from " + first + " to " + last + " # " + current);
output.set(current);
try
{
Thread.sleep(100);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
};
// add 5 number every 500ms
Thread t2 = new Thread() {
public void run()
{
while(true)
{
for(int j = 0; j < 5; j++)
{
numbers.add(insert.getAndIncrement());
}
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
};
// remove all printed numbers every 1000ms
Thread t3 = new Thread() {
public void run()
{
while(true)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
int current = output.intValue();
while(numbers.peek() < current)
numbers.poll();
}
}
};
t1.start();
t2.start();
t3.start();
try
{
t1.join();
t2.join();
t3.join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
Because the queue is "linked" it should handle iterating, adding and removing in constant time and hence be the most efficient implementation you could use.
Not really. The problem is, there's no structure that does what you want in an efficient manner.
You could use ArrayList, iterate over indices and keep an updated current index after inserting at the start (increment by 1), but inserting at the start will not be efficient
You can't use LinkedList because it does not expose the current Node
Your best bet would probably be CursorableLinkedList from Apache Commons Collections (https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/list/CursorableLinkedList.html)
Create a copy of your list before iterating over the items.
Or do you have any other constraints?
I wrote the below code trying to run two threads for calling a function in a for loop, but the results have the same time as if I ran it sequentially without multiple threads. Any thoughts why the multithreading here is not working? Is there a better way to do it? Like for example if I wanted to have 10 threads, using my code this will mean I have to create 10 duplicate run() functions when creating the thread, I wonder if there is an easier way to set the number of threads? Also is it possible to create a number of threads depending on the loop counter so that each loop a thread is created to finish it so if I had 10 loops then 10 threads will run concurrently to finish the processing very fast?
private Thread t1 = new Thread(){
public void run(){
for (int i = 0; i < 2; i++)
{
try {
myfn(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
private Thread t2 = new Thread(){
public void run(){
for (int i = 2; i < 4; i++)
{
try {
myfn(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
public Results getResults() throws IOException, SocketTimeoutException {
t1.start();
t2.start();
try {
t1.join(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
t2.join(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
For running the same task across multiple threads, you're probably looking for a thread pool. Java provides a ThreadPoolExecutor for this.
Here is an introduction to Java concurrency with the following example:
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(() -> {
try {
TimeUnit.SECONDS.sleep(2);
return 123;
}
catch (InterruptedException e) {
throw new IllegalStateException("task interrupted", e);
}
});
future.get(1, TimeUnit.SECONDS);
That example specifically creates a pool with only a single thread, but the parameter to Executors.newFixedThreadPool controls how many threads will be used.
I'm not sure from your original question why you think two threads aren't being utilized.
public class MyThead extend Thread{
private int initValue = 0;
private int upperBound = 0;
public MyThread(int init, int ub){
this.initValue = init;
this.upperBound = ub;
}
public void run(){
for(int i = init; i < upperBound; i++){
myfn(i);
}
}
}
Create threads and start them:
List<Thread> threads = new ArrayList<>();
threads.add(new MyThread(0,2));
threads.add(new MyThread(2,4));
for(Thread t: threads){
t.start()
}
for(Thread t: threads){
t.join();
}
I wrote the below code trying to run two threads for calling a function in a for loop, but the results have the same time as if I ran it sequentially without multiple threads.
There are many reasons why that can happen although it's hard to know what is going on without seeing the myfn(...) code. Here are some possible reasons:
It could be that myfn runs so quickly that running it in different threads isn't going to be any faster.
It could be that myfn is waiting on some other resource in which case the threads can't really run concurrently.
It could be that myfn is blocking on IO (network or disk) and even though you are doing 2 (or more) of them at a time, the disk or the remote server can't handle the increased requests any faster.
Is there a better way to do it? Like for example if I wanted to have 10 threads, using my code this will mean I have to create 10 duplicate run() functions...
The right thing to do here is to create your own class which takes the lower and upper bounds. The right way to do this is to implement Runnable, not extend Thread. Something like:
public class MyRunnable implements Runnable {
private final int start;
private final int end;
public MyRunnable(int start, int end) {
this.start = start;
this.end = end;
}
public void run() {
for (int i = start; i < end; i++) {
myfn(i);
}
}
}
You can then either start the threads by hand or use an ExecutorService which makes the thread maintenance a lot easier:
// this will start a new thread for every job
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.submit(new MyRunnable(0, 2));
threadPool.submit(new MyRunnable(2, 4));
// once you've submitted your last task, you shutdown the pool
threadPool.shutdown();
// then we wait until all of the tasks have run
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
You don't need to copy your threads / loop 10 times, just take the logic and use it appropriately.
public class ExampleThread extends Thread {
private final int start, iterations;
public ExampleThread(int start, int iterations) {
this.start = start;
this.iterations = iterations;
}
#Override public void run() {
for (int i = 0; i < iterations; i++) {
myfn(start + i);
}
}
}
int iterations = 2;
List<Thread> threads = new ArrayList<>();
for (int threadId = 0; threadId < 10; threadId++) {
threads.add(new ExampleThread(threadId * iterations, iterations));
}
threads.forEach(Thread::start);
threads.forEach(t -> {
try {
t.join(0);
} catch (Exception e) {
e.printStackTrace(System.err);
}
});
I am trying to get a grasp on synchronizing threads, but I don't understand the problem I'm encountering.
Can someone please help me diagnose this or, even better, explain how I can diagnose this for myself?
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
public class Controller {
public static void main(String[] args) {
int numThreads = 0;
List<Thread> threads = new ArrayList<>();
if (args.length > 0) {
numThreads = Integer.parseInt(args[0]);
}
else {
System.out.println("No arguments");
System.exit(1);
}
CyclicBarrier barrier = new CyclicBarrier(numThreads);
int arr[][] = new int[10][10];
for (int i = 0; i < numThreads; i++) {
Thread newThread = new Thread(new ThreadableClass(barrier, arr));
threads.add(newThread);
}
for (Thread thread : threads) {
thread.start();
}
}
}
There is a main method (above) which accepts the number of threads I want as a command line argument. And there is a work-flow (below) which I am aiming to have increment all elements in a 2D array and print the array before the next thread has its chance to do the same:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class ThreadableClass implements Runnable {
private CyclicBarrier barrier;
private int arr[][];
public ThreadableClass(CyclicBarrier barrier, int[][] arr) {
this.barrier = barrier;
this.arr = arr;
}
#Override
public void run() {
long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");
for (int i = 0; i < 10; i++) {
changeArray();
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
private synchronized void changeArray() {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
arr[i][j]++;
}
}
printArray();
}
private synchronized void printArray() {
System.out.println(Thread.currentThread().getId() + " is printing: ");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
Imagining the size of the array is 2x2, the expected output would look something like this:
1 1
1 1
2 2
2 2
3 3
3 3
4 4
4 4
...
...
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads) (10 * numThreads)
(10 * numThreads) (10 * numThreads)
Instead, all threads increment the array, and begin printing over one another.
There is nothing surprising about the result. You create n threads. You tell all threads to start. Each threads run() starts with:
long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");
...changeArray();
going to change that shared array. After writing to the array, you try to sync (on that barrier). Its too late then!
The point is: you have 10 different ThreadableClass instances. Each one is operating on its own! The synchronized key word ... simply doesn't provide any protection here!
Because: synchronized prevents two different threads calling the same method on the same object. But when you have multiple objects, and your threads are calling that method on those different objects, than there is no locking! What your code does boils down to:
threadA to call changeArray() .. on itself
threadB to call changeArray() .. on itself
threadC to call changeArray() .. on itself
...
In other words: you give n threads access to that shared array. But then you allow those n threads to enter changeArray() at the same time.
One simple fix; change
private synchronized void changeArray() {
to
private void changeArray() {
synchronized(arr) {
In other words: make sure that the n threads have to lock on the same monitor; in that case the shared array.
Alternatively: instead of making changeArray() a method in that ThreadableClass ... create a class
ArrayUpdater {
int arr[] to update
synchronized changeArray() ...
Then create one instance of that class; and give that same instance to each of your threads. Now the sync'ed method will prevent multiple threads to enter!
Because you are providing new instance for each theard using new ThreadableClass(barrier, arr), basically, all the theadrs are using different ThreadableClass objects, so your code synchronized methods run parallely, so you need to use a single ThreadableClass object as shown below:
ThreadableClass threadableClass= new ThreadableClass(barrier, arr);
for (int i = 0; i < numThreads; i++) {
Thread newThread = new Thread(threadableClass);
threads.add(newThread);
}
The important point is synchronization is all about providing access (i.e., key) to an object for a single thread at a time. If you are using a different object for each thread, threads don't wait for the key because each thread has got its own key (like in your example).
I have been trying to implement a parallel Depth First Search in Java for undirected graph. I wrote this code but it doesn't work properly. It doesn't speed-up.
Main method:
package dfsearch_v2;
import java.util.Calendar;
import java.util.Stack;
import java.util.Random;
public class DFSearch_v2 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
long ts_b, ts_e;
int el_count=100;
int thread_count = 4;
int vertices[][]; // graph matrix
boolean isVisited[] = new boolean[el_count];
for(int i=0;i<el_count;i++){
for(int j=0;j<el_count;j++){
Random boolNumber = new Random();
boolean edge = boolNumber.nextBoolean();
vertices[i][j]=edge ? 1 :
}
}
DFSTest r[] = new DFSTest[thread_count];
ts_b = Calendar.getInstance().getTimeInMillis();
for(int i = 0; i < thread_count; i++) {
r[i] = new DFSTest(el_count,vertices,isVisited);
r[i].start();
}
for(int i = 0; i < thread_count;
try {
r[i].join();
} catch (InterruptedException e) {
}
}
ts_e = Calendar.getInstance().getTimeInMillis();
System.out.println("Time "+(ts_e-ts_b));
}
Thread implementation:
package dfsearch_v2;
import java.util.Stack;
public class DFSTest extends Thread {
int numberOfNodes;
int adj[][];
boolean isVisit[];
public DFSTest(int numberOfNodes, int adj[][],boolean isVisit[]){
this.numberOfNodes = numberOfNodes;
this.adj=adj;
this.isVisit=isVisit;
}
public void run()
{
int k,i,s=0;
Stack<Integer> st = new Stack<>();
for(k=0; k < numberOfNodes; k++) isVisit[k]=false;
for (k = numberOfNodes - 1; k >= 0; k--) {
st.push(k);
}
DFSearch(st, isVisit);
}
private void DFSearch(Stack<Integer> st,boolean isVisit[]){
synchronized(isVisit){
int i,k;
while (!st.empty()) {
k=st.pop();
if (!isVisit[k]) {
isVisit[k] = true;
System.out.println("Node "+k+" is visit");
for(i=numberOfNodes-1; i>=0; i--)
if(adj[k][i]==1) st.push(i);
}
}
}
}
}
Could anybody, please, help me? I am really new to parallel programming.
Thanks
If I understand your program correctly, you are locking on the isVisit array which is shared between all threads - this means that you're not going to get any speedup because only one thread is able to make progress. Try using a ConcurrentHashMap or ConcurrentSkipListMap instead.
// shared between all threads
ConcurrentMap<Integer, Boolean> map = new ConcurrentHashMap<>();
public boolean isVisit(Integer integer) {
return map.putIfAbsent(integer, Boolean.TRUE) != null;
}
private void DFSearch(Stack<Integer> st) {
if(!isVisit(st.pop())) {
...
}
}
The concurrent maps use sharding to increase parallelism. Use the putIfAbsent method in isVisit to avoid a data race (you only want the method to return false for one thread).
As for how to divide the work up among multiple threads, use a ConcurrentLinkedQueue of worker threads. When a thread has no more work to perform, it adds itself to the worker thread queue. When a thread has two edges to traverse, it polls the worker thread queue for an available worker thread, and if one is available it assigns one of the edges to the worker thread. When all threads are on the available thread queue then you've traversed the entire list.
You shouldn't need to synchronize on isVisit, which is what is destroying your parallelism. Multiple readers/multiple writers for a Boolean array should be quite safe.
If at all possible, you should avoid dependencies between threads. To this end, don't use a shared stack (if this is what your code is doing -- it's unclear).
In your case, the amount of work done per vertex is tiny, so it makes sense to batch up work in each thread and only consider handing work on to other threads once some backlog threshold is reached.
I changed the approach a little. Now it uses one global stack which is shared by all the threads and n local stacks where n is the number of threads. Each thread stores the nodes of its sub-tree in its local stack. Initially the global stack contains the root of the tree and only one thread gets access to it while the other threads are waiting to be woken up by the working thread. The working thread retrieves and processes the root from the global stack, adds one successor to its local stack then pushes the rest of the successors, if they exist, to the global stack to be processed by other threads and wakes up all the waiting threads. All the other threads follow the same approach (i.e. when threads get a node from the global stack they push one successor to their local stack and the rest to the global stack then start accessing their local stack until it becomes empty).
Yet, it doesn't speed up. I'll be thankful to all of your further ideas.
Main method:
package dfsearch_v2;
import java.util.Calendar;
import java.util.Random;
public class DFSearch_v2 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
long ts_b, ts_e;
//number of nodes
int el_count=400;
int thread_count = 8;
int gCounter=0;
int vertices[][] = new int[el_count][el_count]; // graph matrix
boolean isVisited[] = new boolean[el_count];
for(int i=0;i<el_count;i++){
for(int j=0;j<el_count;j++){
Random boolNumber = new Random();
boolean edge = boolNumber.nextBoolean();
vertices[i][j]=edge ? 1 : 0;
}
}
DFSearch2 r[] = new DFSearch2[thread_count];
ts_b = Calendar.getInstance().getTimeInMillis();
for(int i = 0; i < thread_count; i++) {
r[i] = new DFSearch2(el_count,vertices,isVisited,gCounter);
r[i].start();
}
for(int i = 0; i < thread_count; i++) {
try {
r[i].join();
} catch (InterruptedException e) {
}
}
ts_e = Calendar.getInstance().getTimeInMillis();
System.out.println("Time "+(ts_e-ts_b));
}
}
Thread implementation:
package dfsearch_v2;
import java.util.Stack;
public class DFSearch2 extends Thread{
private boolean isVisit[];
private final Stack<Integer> globalStack;
int numberOfNodes;
//traversal is done ?
boolean isDone;
int adj[][];
// count visited nodes
int gCounter;
public DFSearch2(int number_Nodes,int adj[][],boolean isVisit[],int gCounter){
this.numberOfNodes=number_Nodes;
this.isVisit = isVisit;
this.globalStack = new Stack<>();
this.isDone=false;
this.adj=adj;
this.gCounter=gCounter;
this.globalStack.push(number_Nodes-1);
}
public void run(){
// local stack
Stack<Integer> localStack = new Stack<>();
while (!isDone) {
int k;
synchronized(globalStack){
k = globalStack.pop();
//pop until k is not visited
while (isVisit[k]) {
if(globalStack.empty()) {
isDone=true;
return;
}else{
k=globalStack.pop();
}
}
}
// traverse sub-graph with start node k
DFSearchNode(localStack,k);
yield();
if(globalStack.empty()) {
isDone = true;
}
// if gCounter is not null unvisited node are pushed in globalStack
if(isDone&&gCounter<numberOfNodes){
isDone=false;
//unvisited nodes are pushed in globalStack
for (int i = 0; i < isVisit.length; i++) {
if (!isVisit[i]) {
globalStack.push(i);
}
}
}
}
}
synchronized private void DFSearchNode(Stack<Integer> localStack, int k){
localStack.push(k);
while (!localStack.empty()) {
int s=localStack.pop();
if (!isVisit[s]) {
isVisit[s] = true;
gCounter++;
//System.out.println("Node "+s+" is visit");
//first element is pushed into localStack and anothers in globalStack
boolean flag = true; // local or global stack (true -> local; false ->global )
for(int i=numberOfNodes-1; i>=0; i--)
{
//
if(i==s) continue;
//push another successors in global stack
if(adj[s][i]==1&&!flag&&!isVisit[s]){//visited nodes are not pushed in globalStack
globalStack.push(i);
}
//push first successor in global stack
if(adj[s][i]==1&&flag&&!isVisit[s]) //visited nodes are not pushed in localStack
{
localStack.push(i);
flag=false; //only first element is pushed into localStack
}
}
}
}
}
}
I am trying to understand threads in Java. As an exercise, I created an Ice Cream class as follows.
public class ThreadIceCream {
private String flavor = "";
private String[] specialFlavors = { "Vanilla", "Chocolate", "Butter Pecan", "Strawberry", "Chocolate Chip", "Cherry", "Coffee" };
// Constructor for ThreadIceCream class
public ThreadIceCream() {
int randInt = (int) (Math.random() * specialFlavors.length);
flavor = specialFlavors[randInt];
System.out.println("Enjoy your " + flavor + " IceCream!");
} }
The ThreadIceCream class is a simple class that creates an IceCream object with a random flavor every time the class is initialized. Here is the TestStub I am using.
public class TestStub {
public static void main(String[] args) {
ThreadIceCream Th1 = new ThreadIceCream();
ThreadIceCream Th2 = new ThreadIceCream();
} }
Now I want to create 10 Icecreams (i.e. Create 10 instances of the ThreadIceCream class simultaneously) and I want to use threads in Java to do this. I tried a few things but they were no were close.
Well it's not really that hard:
Thread[] threads = new Thread[10];
for(int i = 0; i < 10; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
ThreadIceCream tic = new ThreadIceCream();
}
});
threads[i].start();
}
for(int i = 0; i < 10; i++) {
threads[i].join();
}
Sure, this won't do much because the work performed by each thread is so small that the overhead to start the threads is actually higher, but whatever.
You should also learn to use the ExecutorService for higher efficiency. Pure threads are heavyweight and are rarely a good solution for anything, especially in groups. Here's an ExecutorService version of the above:
ExecutorService exec = Executors.newFixedThreadPool(10);
for(int i = 0; i < 10; i++) {
exec.submit(new Runnable() {
public void run() {
ThreadIceCream tic = new ThreadIceCream();
}
});
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
Here we are creating a pool of 10 threads and submitting 10 tasks. The threads are recycled betweeen task executions, so only 10 threads are ever created, no matter how many tasks you submit. Since the tasks are so small several tasks may even be executed on the same thread, but that's actually a good thing.