Threads synchronization in Java
I have a scenario like.... There are four threads named as Thread1, Thread2, Thread3 and Thread4. and there is one counter variable. And I want output as below
Thread1 : value of counter variable is = 0
Thread2 : value of counter variable is = 1
Thread3 : value of counter variable is = 2
Thread4 : value of counter variable is = 3
Thread开发者_如何学编程1 : value of counter variable is = 4
Thread2 : value of counter variable is = 5
Thread3 : value of counter variable is = 6
Thread4 : value of counter variable is = 7
Thread1 : value of counter variable is = 8
Thread2 : value of counter variable is = 9
Thread3 : value of counter variable is = 10
Thread4 : value of counter variable is = 11
Even I have done this by logically. But I want something like, When Thread1 is printing the variable of counter then all the remaining threads should wait.....then after Thread2 should come to the picture and print the counter variable and rest should wait.
Suggest me the best solution for this. Thanks in advance :-)
There is little sense in this, except for understanding synchronization. I'd use a CyclicBarrier
to do this. It's a rather high level abstraction, so you don't have to use wait()
or notifiy()
by yourself.
Alternatively, you could use an Integer
or AtomicInteger
object as variable and pass it around the threads (each one should provide a consume(Integer i)
method which can be called by another thread, then increments and prints the value and passes it to the next thread in the ring). In this variant, the synchronization is handled implicit within your code.
I'm not sure what do you want. Do you want your threads to increment and print variable in order? It doesn't make sense, threads are independent and are running concurrently. That's what they are for.
So let me get this straight: you want to use parallel processing to do serial work.
Basically what you want to do is this:
for(int i=0;i<10;i++)
System.out.println(i);
but then with threads.
Threads are used to do things in parallel. That is what they are for. Trying to force a serial problem into this concept will not only slow down your application but also make it much more error prone.
Unless, of course, this example of yours is very much simplified. Maybe you need to give some more information for us to be able to help, then...
This is an interesting problem, since threads are designed to work side by side independently, rather than locked into a strict order.
I think the simplest way to achieve this is with a fair ReentrantLock, an AtomicInteger and some cautious setup (to ensure that the threads start waiting on the ReentrantLock in the correct order).
Your main thread will need to initialise the counter, create the lock object and lock it, then start the four child threads in order, ensuring each of them arrives at the lock before setting the next thread off.
When all 4 threads are primed, you can release the lock and let the other threads run.
Each worker thread should grab the value from the counter, increment it, display the counter, then release the lock (which will let the next thread run) before reacquiring it.
Note that there is still a race condition here: Thread 2 could race round the loop before Thread 1 starts waiting for the lock again, and so the two threads would end up running in inverted order. To fix this, the worker threads need to wait until enough other threads are waiting until they proceed around the loop (except of course for the final iteration). Not nice, but I fear essential given the listed constraints.
This is not simple code. The lesson to be learned here, I think, is that you shouldn't really use multiple threads to perform inherently serial work! Either that, or you shouldn't care exactly which thread performs which of the serial operations.
I have found two ways for this problem.... but still waiting for experts comments....
First way :-----
package semafore;
import java.util.concurrent.Semaphore;
public class Main { public static void main(String args[]) throws Exception { Semaphore sem = new Semaphore(1, true); Thread thrdA = new Thread(new SyncOutput(sem, "Thread1")); Thread thrdB = new Thread(new SyncOutput(sem, "Thread2")); Thread thrdC = new Thread(new SyncOutput(sem, "Thread3")); Thread thrdD = new Thread(new SyncOutput(sem, "Thread4"));
thrdA.start();
thrdB.start();
thrdC.start();
thrdD.start();
thrdA.join();
thrdB.join();
thrdC.join();
thrdD.join();
}
}
class SyncOutput implements Runnable { Semaphore sem; String msg; private static int val = 0;
SyncOutput(Semaphore s, String m) {
sem = s;
msg = m;
}
public void run() {
for (int i = 0; i < 3; i++){
try {
sem.acquire(1);
System.out.println(msg + " : " + ++val);
Thread.sleep(1000);
} catch (Exception exc) {
System.out.println("Error Writing File");
}
sem.release(1);
}
}
}
Second way :-----
package thread;
class num {
// state variable identifying whose turn it is.
private String whoseTurn ="A";
private int cnt=0;
public boolean writenum(String who) {
String x = Thread.currentThread().getName();
try{
Thread.sleep(1000);
}catch(Exception e){}
if (x.equalsIgnoreCase(whoseTurn)) {
System.out.println(x+":"+cnt++);
if(x.equalsIgnoreCase("A"))
whoseTurn = "B";
else if(x.equalsIgnoreCase("B"))
whoseTurn = "C";
else if( x.equalsIgnoreCase("C"))
whoseTurn = "D";
else if( x.equalsIgnoreCase("D"))
whoseTurn = "A";
}
return true;
}
}
public class Game {
public static void main(String args[]) {
num ob = new num();
Thread A = new Thread(new Player("A", ob));
Thread B = new Thread(new Player("B", ob));
Thread C = new Thread(new Player("C", ob));
Thread D = new Thread(new Player("D", ob));
A.setName("A");
B.setName("B");
C.setName("C");
D.setName("D");
A.start();
B.start();
C.start();
D.start();
try {
// Wait 5 seconds
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) { }
ob.writenum("DONE"); // cause the players to quit their threads.
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) { }
}
}
class Player implements Runnable {
num area; // Table where they play
String who;
public Player(String who, num area) {
this.area = area;
this.who = who;
}
public void run() {
while (area.writenum(who));
}
}
精彩评论