I have been going through the program which starts three threads and print their corresponding value such that T3 is executed first, then the T1 thread, and lastly the T2 thread is executed. Below is the program.
I just want to know if you guys could help in converting this program with respect to countdown latch, as I want to develop it using this mechanism or it can be also done through counting semaphore.
From the answer to this related question:
public class Test {
static class Printer implements Runnable {
private final int from;
private final int to;
private Thread joinThread;
Printer(int from, int to, Thread joinThread) {
this.from = from;
this.to = to;
this.joinThread = joinThread;
}
#Override
public void run() {
if(joinThread != null) {
try {
joinThread.join();
} catch (InterruptedException e) { /* ignore for test purposes */ }
}
for (int i = from; i <= to; i++) {
System.out.println(i);
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread T3 = new Thread(new Printer(10, 15, null));
Thread T1 = new Thread(new Printer(1, 5, T3));
Thread T2 = new Thread(new Printer(6, 10, T1));
T1.start();
T2.start();
T3.start();
}
}
We consider each pair of threads Tw, Ts such as Tw is waiting on Ts to commence its work. In your setup, there are 2 such pairs:
T1, T3
T2, T1
For each pair, we will create one CountDownLatch, and provide it to each thread of the pair. Then Tw will call await on the latch before starting its work, and Ts will call countDown at the end of its own work.
Since T1 belongs to both pairs, it will receive both latches. However, in the first case, T1 is a waiting thread, and in the second, T1 is a signaling thread, therefore its code will have to be amended accordingly.
Of course you will have to remove the join calls and related infrastructure.
Since your question title asks about latch implementation, let's just briefly say that the same semantics can be produced using a Semaphore initialized at 0, and where countDown would actually be a release of the semaphore, while await would be an acquire of that semaphore.
public class Test {
private CountdownLatch latch;
private Runnable runnable;
class Tw implements Runnable {
Tw(CountdownLatch l, Runnable r) {
latch = l;
runnable = r;
}
#override
public void run(){
latch.await();
runnable.run();
}
}
class Ts implements Runnable {
CountdownLatch latch;
Runnable runnable;
Ts(CountdownLatch l, Runnable r){
latch = l;
runnable = r;
}
#override
public void run(){
runnable.run();
latch.countDown();
}
}
static class Printer implements Runnable {
private final int from;
private final int to;
Printer(int from, int to) {
this.from = from;
this.to = to;
}
#Override
public void run() {
for (int i = from; i <= to; i++) {
System.out.println(i);
}
}
public static void main(String[] args) throws InterruptedException {
CountdownLatch l31 = new CountdownLatch(1), l12 = new CountdownLatch(1);
Thread T3 = new Thread(new Ts(l31, new Printer(10, 15, null)));
Thread T1 = new Thread(new Tw(l31, new Ts(l12, new Printer(1, 5, T3))));
Thread T2 = new Thread(new Tw(l12, new Printer(6, 10, T1)));
T1.start();
T2.start();
T3.start();
}
}
The proposed sample implementation uses auxiliary runnables to take care of the latching process, thus allowing us to compose each task using these runnables, instead of deriving the Printer class for each specific case (we save at least one class).
The Semaphore based similar implementation is left as an exercise for the reader.
Related
I'm trying to create multiple threads in a java program and have them perform arithmetic operations on integers passed as command-line arguments. Obviously neither of the thread classes I'm trying to pass to are in the main method so how can I still access a variable like args[0] from these classes?
public class Mythread {
public static void main(String[] args) {
Runnable r = new multiplication();
Thread t = new Thread(r);
Runnable r2 = new summation();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}
class summation implements Runnable{
public void run(){
System.out.print(args[0]);
}
}
class multiplication implements Runnable{
public void run(){
System.out.print(args[1]);
}
}
You should pass in the necessary information in the constructor
class Summation implements Runnable {
private final String info;
public Summation(String info) {
this.info = info;
}
#Override
public void run(){
System.out.print(info);
}
}
Then you can pass in the args values to your threads in main so that you have them in your runnables / threads
public class Mythread {
public static void main(String[] args) {
Runnable r = new multiplication(args[1]);
Thread t = new Thread(r);
Runnable r2 = new summation(args[0]);
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}
I'm trying to figure out how synchronized methods work. From my understanding I created two threads T1 and T2 that will call the same method addNew, since the method is synchronized shouldn't it execute all the iterations of the for loop for one thread and then the other? The output keeps varying, sometimes it prints it right, other times it prints values from T1 mixed with T2 values. The code is very simple, can someone point out what am I doing wrong? Thank you.
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new A());
Thread t2 = new Thread(new A());
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
public class B {
public synchronized void addNew(int i){
Thread t = Thread.currentThread();
for (int j = 0; j < 5; j++) {
System.out.println(t.getName() +"-"+(j+i));
}
}
}
public class A extends Thread {
private B b1 = new B();
#Override
public void run() {
b1.addNew(100);
}
}
Each A instance has its own B instance. The method addNew is an instance method of B. Therefore, the lock acquired implicitly during calls to addNew is the lock on the receiver B instance. Each thread is calling addNew on a different B, and therefore locking on different locks.
If you want all B instances to use a common lock, create a single shared lock, and acquire it in the body of addNew.
Both A objects have their own B object. You need them to share a B so the synchronization can have an effect.
try this :
public class Main {
public static void main(String[] args) {
A a = new A();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
class B {
public synchronized void addNew(int i){
Thread t = Thread.currentThread();
for (int j = 0; j < 5; j++) {
System.out.println(t.getName() +"-"+(j+i));
}
}
}
class A extends Thread {
private B b1 = new B();
#Override
public void run() {
b1.addNew(100);
}
}
Example One:
public class Test {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
Runnable t1 = new MyRunnable("A", 2000);
Runnable t2 = new MyRunnable("B", 3600);
Runnable t3 = new MyRunnable("C", 2700);
Runnable t4 = new MyRunnable("D", 600);
Runnable t5 = new MyRunnable("E", 1300);
Runnable t6 = new MyRunnable("F", 800);
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
pool.shutdown();
}
}
class MyRunnable implements Runnable {
private static AtomicLong aLong = new AtomicLong(10000);
private String name;
private int x;
MyRunnable(String name, int x) {
this.name = name;
this.x = x;
}
public void run() {
System.out.println(name + " excute" + x + ",money:" + aLong.addAndGet(x));
}
}
this thread is not safe in this sample.
Example Two
public class CountingFactorizer implements Servlet {
private final AtomicLong count = new AtomicLong(0);
public void service(ServletRequest req, ServletResponse resp) {
count.incrementAndGet();
}
}
why is this thread safe? somebody can tell me?
I'm study thread in java, but cannot understand two sample. Are they different?
As far I can see both are thread safe. In both examples the static, class level, member is AtomicLong that is thread safe by definition. All other members in the first example are instance level member and are executed in different threads, so no conflicts at all.
This article explains "Double-Checked Locking" where the idea is to reduce lock contention. As the article explains it does not work. See the code sample in the table "(Still) Broken multithreaded version "Double-Checked Locking" idiom".
Now I think I found a variant that should work. Question is whether that is correct. Let's say we have a consumer and a producer that exchange data through a shared queue:
class Producer {
private Queue queue = ...;
private AtomicInteger updateCount;
public void add(Data data) {
synchronized(updateCount) {
queue.add(task);
updateCount.incrementAndGet();
}
}
}
class Consumer {
private AtomicInteger updateCount = new AtomicInteger(0);
private int updateCountSnapshot = updateCount.get();
public void run() {
while(true) {
// do something
if(updateCountSnapshot != updateCount.get()) {
// synchronizing on the same updateCount
// instance the Producer has
synchronized(updateCount) {
Data data = queue.poll()
// mess with data
updateCountSnapshot = updateCount.get();
}
}
}
}
}
Question now is whether you think this approach works. I'm asking to be sure, because tons of things would break if it doesn't ... The idea is to reduce lock contention when only entering a synchronized block in the consumer when the updateCount has changed in the meanwhile.
I suspect you are looking more for a Code Review.
You should consider the following:
This is not double-checked locking.
Your consumer will spin on nothing and eat cpu while no data is arriving.
You use an AtomicInteger as a Semaphore.
A BlockingQueue will do all of this for you.
You haven't properly ensured that updateCount is shared.
You do not have to synchronize on atomics.
Here's a simple Producer/Consumer pair for demonstration.
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final Queue<Integer> queue;
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final Queue<Integer> queue;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.poll();
if (i != null) {
ended = i == End;
System.out.println(i);
}
}
}
}
public void test() throws InterruptedException {
Queue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
Please see the program below
public class TestVolatile implements Runnable {
public static volatile int counter;
public static String lock = "lock";
public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile(),"Thread-1");
Thread t2 = new Thread(new TestVolatile(),"Thread-2");
t1.start();
t2.start();
}
public void run() {
synchronized(this) {
System.out.println(Thread.currentThread()+"-"+counter);
counter++;
}
}
}
If I run this program multiple times, I get 3 different results.
first is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-0
second is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-1
third is
Thread[Thread-1,5,main]-1
Thread[Thread-2,5,main]-0
But if change the lock object from "this" to "lock", I get 2 different results
first is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-1
second is
Thread[Thread-1,5,main]-1
Thread[Thread-2,5,main]-0
My assumption when writing the program was that in either case the "counter" should never come 0 in both statements.
Can somebody explain?
You create two TestVolatile objects. The "this" keyword refers to the TestVolatile object being run in the thread. Thus you do not synchronize on the same object in the first example.
If you change the code like this, then the first example starts working:
public static void main(String[] args) {
TestVolatile testVolatile = new TestVolatile();
Thread t1 = new Thread(testVolatile,"Thread-1");
Thread t2 = new Thread(testVolatile,"Thread-2");
t1.start();
t2.start();
}
It's probably not what you're looking for, but if you want to avoid the use of synchronized and volatile, you should use an instance of AtomicInteger:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html
Use the getAndIncrement method to show the same behavior as in your example.
public class TestVolatile implements Runnable {
public static AtomicInteger counter = new AtomicInteger();
public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile(),"Thread-1");
Thread t2 = new Thread(new TestVolatile(),"Thread-2");
t1.start();
t2.start();
}
public void run() {
System.out.println(Thread.currentThread() + " - " + counter.getAndIncrement());
}
}