I am new in the multithreading in Java, so I have a question about how to reduce calculation time in this example, without using Executors, Frameworks, etc, only plain threads?
public static void main(String[] args) throws TestException {
Set<Double> res = new HashSet<>();
for (int i = 0; i < TestConsts.N; i++) {
res.addAll(TestCalc.calculate(i));
}
System.out.println(res);
}
And there is calculation method:
private static final Random rnd = new Random();
public static Set<Double> calculate(int num) throws TestException {
// Emulates calculation delay time.
try {
Thread.sleep(rnd.nextInt(1000) + 1);
}
catch (InterruptedException e) {
throw new TestException("Execution error.", e);
}
Set<Double> res = new HashSet<>();
int n = rnd.nextInt(num + 1) + 1;
for (int j = 0; j < n; j++) {
res.add(rnd.nextDouble());
}
return res;
}
The reason for not using any frameworks is that I want to understand the original multithreading.
Thanks you in advance.
Try to create a class that extends Thread or implements Runnable, add the details on the calculate() method to the run() method of the new class.
Now in the for loop of main function create new threads of type of the new class and start() them.
Also you need to synchronize the threads.
Reference
I will try to answer on a conceptual level:
You could spawn a Thread for each task
You could spawn n threads that use a (synchronized) Queue<Task> to obtain more work
You will have to synchronize whenever a thread finishes its part.
Related
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 300;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
Why the output is "n is: 300"? n isn't explicitly synchronized. And if I uncomment "Thread.sleep", the output is "n is: 299 or less".
I changed your code this way:
private static final int NTHREADS = 300;
private static AtomicInteger n = new AtomicInteger();
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
n.incrementAndGet();
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
You have to deal with racing-conditions. All the 300 threads are modifying n concurrently. For example: if two threads would have read and increment n concurrently than both increment n to the same value.
That was the reason why n wasn't always 300, you lost one increment in such a situation. And this situation could have occurred zero or many times.
I changed n from int to AtomicInteger which is thread safe. Now everything works as expected.
You better use AtomicInteger.
This question will help you with description and example: Practical uses for AtomicInteger
Static context need to have lock on the class and not on the Object. If you need a static variable to be synchronized and do not need it to be cached inside the thread locally you need to declare it as volatile.
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 30;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 1000; j++) // run a long time duration
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
output "n is: 29953"
I think the reason is, the threads run a short time duration, and the jvm don't make a context switch.
Java static field will be synchronized among threads?
No. You should make it volatile or synchronize all access to it, depending on your usage patterns.
I am wondering why the result is not 400 000. There are two threads why does it gets blocked?
class IntCell {
private int n = 0;
public int getN() {return n;}
public void setN(int n) {this.n = n;}
}
class Count extends Thread {
private static IntCell n = new IntCell();
#Override public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
public static void main(String[] args) {
Count p = new Count();
Count q = new Count();
p.start();
q.start();
try { p.join(); q.join(); }
catch (InterruptedException e) { }
System.out.println("The value of n is " + n.getN());
}
}
Why there is so problem with that?
Because the way you increment your variable is not an atomic operation indeed to increment it you:
Get the previous value
Add one to this value
Set a new value
They are 3 operations not done atomically you should either us a synchronized block or use an AtomicInteger instead.
With a synchronized block it would be something like:
synchronized (n) {
temp = n.getN();
n.setN(temp + 1);
}
With an AtomicInteger you will need to rewrite your code as next:
class IntCell {
private final AtomicInteger n = new AtomicInteger();
public int getN() {return n.get();}
public void incrementN(int n) {this.n.addAndGet(n);}
}
for (int i = 0; i < 200000; i++) {
n.incrementN(1);
}
The approach with an AtomicInteger is non blocking so it will be faster
When two threads access one object at the same time, they interfere with each other, and the result is not deterministic. For example, imagine that p reads the value of n and gets, say, 0, then q reads the same value and gets 0 too, then p sets value to 1 and q also sets it to 1 (because it still thinks that it has value 0). Now the value of n is increased by 1, even though both counters "incremented" it once. You need to use synchronized block to make sure the counters won't interfere with each other. See https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html for more.
The problem here is that you allow for race conditions. Consider the block inside the loop:
temp = n.getN();
n.setN(temp + 1);
The code context switch between the time you get the current N and by the time you increment it, making you set an "old" value. One way around this is to ensure the inner part of the loop runs in a synchronized block:
for (int i = 0; i < 200000; i++) {
synchronized (n) { / Here!
temp = n.getN();
n.setN(temp + 1);
}
}
I have just found HiddenInterator example, in the Java concurrency in practice book.
class ConcurentIterator implements Runnable {
// because of final it is immutable, so it is thread safe
private final Set<Integer> v = new HashSet<Integer>();
//private final Vector<Integer> v = new Vector<Integer>();
public synchronized void add(Integer i) {
v.add(i);
}
public synchronized void remove(Integer i) {
v.remove(i);
}
public void addTenThings() {
Random r = new Random();
for (int i = 0; i < 10; i++) {
add(r.nextInt());
System.out.println("DEBUG: added ten elements to " + v);
}
}
public void run() {
addTenThings();
}
}
I understand everything! that's nice!
I have the following question:
In java we have concurrent collections for instance: ConcurentSkipListMap, ConcurrentHashMap, where the problem is fixed. But I'm interested which are the classes where the problem can happen(where it is not fixed)? For instance can it be occur on vector? When I was testing, I can't throw the ConcurentModificationException in the vector.
Testing method:
public static void main(String[] args) {
Thread[] threadArray = new Thread[200];
ConcurentIterator in = new ConcurentIterator();
for (int i = 0; i < 100; i++) {
threadArray[i] = new Thread(in);
}
for (int i = 0; i < threadArray.length; i++) {
threadArray[i].start();
}
}
Thread unsafe collection will exhibit this behavior of throwing ConcurrentModificationException - examples are Arraylist, HashSet, HashMap, TreeMap, LinkedList...
Thread safe collections like vector will also exhibit this behavior if the collection is altered while it is being iterated without using the iterator in use.
What's your objective here - to know the name of all collections that can throw this exception; it is best if we focus on the concept and take individual examples to demonstrate the concept.
Adding an example below for the code that uses Vector and would still throw ConcurrentModificationException - the idea is that removals should be done via iterator or else the collection will fail signalling a concurrent attempt at modifying the collection
public static void main(String[] args) {
Vector<Integer> numbers = new Vector<Integer>(Arrays.asList(new Integer[]{1,2,3,4,5,6}));
for (Integer integer : numbers) {
System.out.println(integer);
numbers.remove(2);
}
}
At work training, I'm writing a Java (in which I have 0 experience) program that should meet the following criteria:
Write a program that replicates distributed computing application
Create central 'scheduler' object which contains a list of M random numbers
Create N processor threads that retrieve a number from the scheduler then loop that many times before requesting another number
If no numbers are available from the scheduler, wait to request another number.
If no more numbers are left, all the threads should end.
So far, I created an object with an array of random numbers, but I really don't know how to proceed with multithreading. Could someone please guide me through it? This is what I have so far, along with comments indicating pseudo code.
public class ThreadDemo extends Thread
{
//create new array of arbitrary size 5
static int SIZE = 5;
static int[] myIntArray = new int[SIZE];
public ThreadDemo()
{
start();
}
class RunnableThread implements Runnable {
Thread runner;
public RunnableThread() {
}
public RunnableThread(String threadName) {
runner = new Thread(this, threadName); // (1) Create a new thread.
System.out.println(runner.getName());
runner.start(); // (2) Start the thread.
}
public void run() {
//Display info about this particular thread
System.out.println(Thread.currentThread());
}
}
public static void main(String[] args)
{
for(int i=0; i<SIZE; i++)
{
myIntArray[i] = (int)(Math.random() * 10);
}
ThreadDemo scheduler = new ThreadDemo();
//create M processor threads that retrieve number from scheduler
//for(int i=0; i<SIZE; i++)
//
//if no threads available
//make the scheduler thread wait() ??
//if empty
//stop() the scheduler thread ??
}
}
Could anyone steer me in the right direction?
Thank you!
As a first pointer: don't start threads in a constructor and don't use the Runnable object to start a thread using itself. It's very confusing to whoever reads the code.
Here's my take on this problem (hope I didn't get carried away):
class Scheduler {
private int[] numbers;
private AtomicInteger current = new AtomicInteger();
public Scheduler(int count) {
Random rand = new Random();
numbers = new int[count];
for(int i = 0; i < count; i++) {
numbers[i] = rand.nextInt();
if(numbers[i] < 0) numbers[i] *= -1;
}
}
public int getNextNumber() {
int local = current.incrementAndGet();
if(local >= numbers.length) {
return -1;
}
return numbers[local];
}
}
First, we define the Scheduler class that holds an array of random (positive) integers and returns a number from the array on-demand, based on an atomically incrementing counter.
class Task implements Runnable {
private Scheduler scheduler;
public Task(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void run() {
while(true) {
int limit = scheduler.getNextNumber(); // get next number
if(limit == -1) return; // no more numbers
System.out.println(limit);
for(int i = 0; i < limit; i++) {
// spin
}
}
}
}
The Task class holds the code that each thread executes. Each thread loops indefinitely requesting numbers from the Scheduler, until the array is exhausted.
public class Test {
public static void main(String[] args) throws InterruptedException {
Scheduler s = new Scheduler(100);
ExecutorService exec = Executors.newFixedThreadPool(4);
for(int i = 0; i < 4; i++) {
exec.submit(new Task(s));
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
In the main class we set up a thread pool and execute 4 threads to do the aforementioned tasks.
This is a good place to start. IT will also help to look at a executor service. Here is an example.
You might also want to take a look at some of the concurrent collections. It might be worth using a queue instead of an array so its a little cleaner to tell when something has been pulled out of it.
As per my understanding of your Homework, you need to create a producer and worker thread units. Please refer the below link, which will suits your requirement.
http://www.exampledepot.com/egs/java.lang/WorkQueue.html
Thanks
Thanikachalan
You might want to take a look at te ThreadPoolExecutor
You should end up with something like this.
public static void main(){
ThreadPoolExecutor tpe = new ThreadPoolExecutor(...);
List<Integer> numbers = getNumberList();
for(Integer i : numbers){
tpe.submit(new MyRunnable(i) {
Integer i;
public MyRunnable(Integer i){
this.i=i;
}
#Override
public void run() {
dosomethingWith(i);
}
}
}
}
I am reading "Java Concurrency in practice" and looking at the example code on page 51.
This states that if a thread has references to a shared object then other threads may be able to access that object before the constructor has finished executing.
I have tried to put this into practice and so I wrote this code thinking that if I ran it enough times a RuntimeException("World is f*cked") would occur. But it isn't doing.
Is this a case of the Java spec not guaranting something but my particular implementation of java guaranteeing it for me? (java version: 1.5.0 on Ubuntu) Or have I misread something in the book?
Code: (I expect an exception but it is never thrown)
public class Threads {
private Widgit w;
public static void main(String[] s) throws Exception {
while(true){
Threads t = new Threads();
t.runThreads();
}
}
private void runThreads() throws Exception{
new Checker().start();
w = new Widgit((int)(Math.random() * 100) + 1);
}
private class Checker extends Thread{
private static final int LOOP_TIMES = 1000;
public void run() {
int count = 0;
for(int i = 0; i < LOOP_TIMES; i++){
try {
w.checkMe();
count++;
} catch(NullPointerException npe){
//ignore
}
}
System.out.println("checked: "+count+" times out of "+LOOP_TIMES);
}
}
private static class Widgit{
private int n;
private int n2;
Widgit(int n) throws InterruptedException{
this.n = n;
Thread.sleep(2);
this.n2 = n;
}
void checkMe(){
if (n != n2) {
throw new RuntimeException("World is f*cked");
}
}
}
}
You don't publish the reference until after the constructor has finished, change Widgit like this:
private class Widgit{ // NOTE: Not class is not static anymore
private int n;
private int n2;
Widgit(int n) throws InterruptedException{
this.n = n;
w = this; // publish reference
Thread.sleep(2);
this.n2 = n;
}
void checkMe(){
if (n != n2) {
throw new RuntimeException("World is f*cked");
}
}
Should now throw.
Edit: You should also declare the Widgit field as volatile:
private volatile Widgit w;
Well, you need to understand the issues a little more. It isn't really a case of anything being or not being "guaranteed." With concurrency problems, nothing is really guaranteed unless you really do specific things to force the problem to happen. You're just relying on the hope that enough runs should produce, which is not the case. These kinds of problems are hard to predict, which is why concurrency is a hard problem. You could try doing more work in your functions, but I assure you these are real problems that the runtime is not going to save you from.
Before sleeping, start a new thread which prints the value of n2. You will see the second thread can access the object before the constructor has finished.
The following example demonstrates this on the Sun JVM.
/* The following prints
Incomplete initialisation of A{n=1, n2=0}
After initialisation A{n=1, n2=2}
*/
public class A {
final int n;
final int n2;
public A() throws InterruptedException {
n = 1;
new Thread(new Runnable() {
public void run() {
System.out.println("Incomplete initialisation of " + A.this);
}
}).start();
Thread.sleep(200);
this.n2 = 2;
}
#Override
public String toString() {
return "A{" + "n=" + n + ", n2=" + n2 + '}';
}
public static void main(String... args) throws InterruptedException {
System.out.println("After initialisation " + new A());
}
}
This will never throw a RunTimeException because your Widgit instance variable w remains null until the constructor code has executed. While your main thread is sleeping in the Widgit constructor, your Checker instance is hitting NullPointerException constantly as the w variable is still null. When your main thread finishes construction, the two int variables in Widgit are equal.