Przykład

public static void main( String[] args ) {
Data data = new Data();
final Consumer consumer = new Consumer( data );
final Producer producer = new Producer( data );

(new Thread( new Runnable() {
public void run() {
consumer.consume();
}
})).start();


(new Thread( new Runnable() {
public void run() {
producer.produce();
}
})).start();
}

public static final class Data {
public Data() {
super();
}
public int getValue() {
return value;
}
public void setValue( int value ) {
this .value = value;
}
private int value = 0;
}

public static final class Consumer {
public Consumer( Data data ) {
this .data = data;
}

public void consume() {
System.out.println( "Consumer: wywołano metodę consume" ); //$NON-NLS-1$
System.out.println( "Consumer: ustępowanie..." ); //$NON-NLS-1$
Thread.yield();
System.out.println( "Consumer: wartość to " + data.getValue() ); //$NON-NLS-1$
System.out.println( "Consumer: zamykanie" ); //$NON-NLS-1$
}

private Data data;
}

public static final class Producer {
public Producer( Data data ) {
this .data = data;
}
public void produce() {
System.out.println( "Producer: wywołano metodę produce" ); //$NON-NLS-1$
try { Thread.sleep( 3000 ); } catch (InterruptedException e) {}
data.setValue( 1 );System.out.println( "Producer: zamykanie" ); //$NON-NLS-1$
}
private Data data;
}

Rozwiązanie
Zamiast metody yield() użyj metod wait()/notify().

public static void main( String[] args ) {
Data data = new Data();
Lock lock = new Lock();
final Consumer consumer = new Consumer( data, lock );
final Producer producer = new Producer( data, lock );

(new Thread( new Runnable() {
public void run() {
consumer.consume();
}
})).start();


(new Thread( new Runnable() {
public void run() {
producer.produce();
}
})).start();
}

public static final class Data {
public Data() {
super();
}
public int getValue() {
return value;
}
public void setValue( int value ) {
this .value = value;
}
private int value = 0;
}

public static final class Lock {
public Lock() {
super();
lock();
}
public boolean isAvailable() {
return available;
}
public void lock() {
available = false;
}
public void unlock() {
available = true;
}
private boolean available = false;
}

public static final class Consumer {
public Consumer( Data data, Lock lock ) {
this .data = data;
this .lock = lock;
}

public void consume() {
System.out.println( "Consumer: wywołano metodę consume" ); //$NON-NLS-1$
System.out.println( "Consumer: oczekiwanie..." ); //$NON-NLS-1$
synchronized ( lock ) {
try {
lock.wait();
} catch (InterruptedException e) {}
}
System.out.println( "Consumer: wartość to " + data.getValue() ); //$NON-NLS-1$
System.out.println( "Consumer: zamykanie" ); //$NON-NLS-1$
}

private Data data;
private Lock lock;
}

public static final class Producer {
public Producer( Data data, Lock lock ) {
this .data = data;
this .lock = lock;
}
public void produce() {
System.out.println( "Producer: wywołano metodę produce" ); //$NON-NLS-1$
synchronized ( lock ) {
try { Thread.sleep( 3000 ); } catch (InterruptedException e) {}
data.setValue( 1 );System.out.println( "Producer: zamykanie" ); //$NON-NLS-1$
lock.unlock();
lock.notifyAll();
}
}
private Data data;
private Lock lock;
}