问题
I'm trying to print numbers 1-20 with two threads:
- Even thread - Print only even numbers.
- Odd thread - print only odd numbers.
I also have a lock object for synchronization.
My application is stuck. Can you tell me what is the problem?
My code:
public class runIt
{
public static void main(String[] args)
{
Odd odd = new Odd("odd thread");
Even even = new Even("even thread");
odd._t.start();
even._t.start();
try{
odd._t.join();
even._t.join();
}
catch (InterruptedException e){
System.out.println(e.getMessage());
}
}
}
public class Constants{
static Object lock = new Object();
}
public class Even implements Runnable{
Thread _t;
String _threadName;
public Even(String threadName){
_threadName = threadName;
_t = new Thread(this);
}
@Override
public void run(){
for (int i = 0; i < 20; i++){
if (i % 2 == 0){
synchronized (Constants.lock){
try{
Constants.lock.wait();
Constants.lock.notifyAll();
}
catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(_threadName + " " + i + " ");
}
}
}
}
}
public class Odd implements Runnable{
Thread _t;
String _threadName;
public Odd(String threadName){
_threadName = threadName;
_t = new Thread(this);
}
@Override
public void run(){
for (int i = 0; i < 20; i++){
if (i % 2 == 1){
synchronized (Constants.lock){
try{
Constants.lock.wait();
Constants.lock.notifyAll();
}
catch (InterruptedException e1){
e1.printStackTrace();
}
System.out.println(_threadName + " " + i + " ");
}
}
}
}
}
My output should be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Thank you for the assistance, Tam.
回答1:
You are misusing synchronized
and wait
by calling wait on the object you used in synchronized
, immediately, without having a check inside the synchronized block in a loop. NEVER DO THAT AGAIN.
In fact here's what happen :
- at
synchronized
line you get a lock onConstants.lock
- at
wait
line, you release the lock onConstants.lock
and wait for a notify from another thread.
So what is happening in your prog :
- first thread (no matter what it is) reaches
synchronized
and proceed blocking the second - first thread releases the synchonizing lock and put itself in a wait state for a notify
- second thread goes through
synchronized
because first has released the lock - both thread are now waiting for a notify that will never occur
回答2:
Below code will help to someone,
public class MyClass {
private static Object lock = new Object();
public static void main(String args[]){
Runnable runnable1 = new Runnable() {
@Override
public void run() {
for(int i=1; i<20; i=i+2){
synchronized (lock) {
System.out.println("Thread 1: "+i);
try {
lock.notifyAll();
lock.wait();
} catch (InterruptedException e) {
System.out.println("Error in Thread 1: "+e.getMessage());
}
}
}
}
};
Runnable runnable2 = new Runnable() {
@Override
public void run() {
for(int i=2; i<=20; i=i+2){
synchronized (lock) {
System.out.println("Thread 2: "+i);
try {
lock.notifyAll();
lock.wait();
} catch (InterruptedException e) {
System.out.println("Error in Thread 2: "+e.getMessage());
}
}
}
}
};
Thread thread1 = new Thread(runnable1);
Thread thread2 = new Thread(runnable2);
System.out.println("Thread Start: ");
thread1.start();
thread2.start();
}
}
回答3:
You can find the explanation in the site mentioned in package declaraion: Here's the working code:
public class MultipleThreading {
int count = 1;
int MAX = 20;
public void printOdd() {
synchronized (this) {
while (count < MAX) {
while (count % 2 == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(count + " ");
count++;
notify();
}
}
}
public void printEven() {
synchronized (this) {
while (count < MAX) {
while (count % 2 == 1) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(count + " ");
count++;
notify();
}
}
}
public static void main(String[] args) {
MultipleThreading mt = new MultipleThreading();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
mt.printEven();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
mt.printOdd();
}
});
t1.start();
t2.start();
}
}
回答4:
Everyone on the Stack Overflow tried the same solution. Checkout a different implementation for the same.
public class PrintSequenceUsingTwo {
public static void main(String[] args) {
ThreadSequence sequence = new ThreadSequence();
Thread t1 = new Thread(()-> {try {
sequence.print();
} catch (InterruptedException e) {
e.printStackTrace();
}},"t1");
Thread t2 = new Thread(()-> {try {
sequence.print();
} catch (InterruptedException e) {
e.printStackTrace();
}},"t2");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ThreadSequence {
private static int var = 0;
private int limit = 10; //set the variable value upto which you want to print
public synchronized void print() throws InterruptedException {
while (var<limit) {
notify();
System.out.println("Current Thread "+Thread.currentThread().getName()+" Value : "+(++var));
wait();
}
notify();
}
}
来源:https://stackoverflow.com/questions/24720849/print-numbers-1-20-with-two-threads-in-java