Java Concurrency Problems with Example

Java Concurrency Problems with Example


Concurrency Problems with Example In Java
Up to this point, you’ve been learning about sequential programming. Everything in a program happens one step at a time. 
A primary reason why concurrent programming can be confusing is that there is more than one problem to solve using concurrency, more than one approach to implementing concurrency, and no clean mapping between the two issues (and often a blurring of the lines all around). 
As a result, you’re forced to understand all issues and special cases in order to use concurrency effectively.
The problems that you solve with concurrency can be roughly classified as "speed" and manageability of design.
concurrency can often improve the performance of programs running on a single processor.
Without concurrency, the whole program comes to a stop until the external condition changes.
If the program is written using concurrency, however, the other tasks in the program can continue to execute when one task is blocked, so the program continues to move forward.
In fact, from a performance standpoint, it makes no sense to use concurrency on a single-processor machine unless one of the tasks might block. 
Now we will see Examples - 
Example  - 
// The most basic use of the Thread class.
public class BasicThreadsHere {
public static void main(String[] args) {
Thread p = new Thread(new LiftOff());
p.start();
System.out.println("Waiting for LiftOff");
}
Output -
Waiting for LiftOff

#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), 
Example 2 - 
// An example of CountDownLatch.
import java.util.concurrent.CountDownLatch;
class CDLDemo {
public static void main(String args[]) {
CountDownLatch cdl = new CountDownLatch(5);
System.out.println("Starting");
new MyThread(cdl);
try {
cdl.await();
} catch (InterruptedException exc) {
System.out.println(exc);
}
System.out.println("Done");
}
}
class MyThread implements Runnable {
CountDownLatch latch;
MyThread(CountDownLatch c) {
latch = c;
new Thread(this).start();
}
public void run() {
for(int i = 0; i<5; i++) {
System.out.println(i);
latch.countDown(); // decrement count
}
}
}
Output - 
Starting
0
1
2
3
4
Done
Example 3 - Producing return values from tasks
import java.util.concurrent.*;
import java.util.*; 

class TaskWithTheResult implements Callable<String> {
private int id;
public TaskWithTheResult(int id) {
this.id = id;
}
public String call() {
return "result of TaskWithTheResult " + id;
}
}
public class CallableDemo {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results =
new ArrayList<Future<String>>();
for(int i = 0; i < 10; i++)
results.add(exec.submit(new TaskWithTheResult(i)));
for(Future<String> fs : results)
try {
// get() blocks until completion:
System.out.println(fs.get());
} catch(InterruptedException e) {
System.out.println(e);
return;
} catch(ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}
Output - 
result of TaskWithResult 0
result of TaskWithResult 1
result of TaskWithResult 2
result of TaskWithResult 3
result of TaskWithResult 4
result of TaskWithResult 5
result of TaskWithResult 6
result of TaskWithResult 7
result of TaskWithResult 8
result of TaskWithResult 9