erwartete ich versuche, so etwas zu tun:Synchronisiert und Threads nicht funktioniert als
Es gibt eine Klasse Q
die ein Feld n
und zwei Methoden put()
und get()
genannt hat, die den Wert von n-Sets oder ruft den Wert von n. Und dann gibt es zwei Klassen Producer
und Consumer
. Producer
Klasse hat einen Thread, der ruft put
und consumer
Klasse hat einen Thread, der get
ruft. Ich versuche, es zu synchronisieren ein Object lock
verwendet, die die einzigen Instanz von Singleton-Klasse ist LockClass.
So Q meine Klasse, hier ist:
public class Q {
int n;
public void put(int n){
System.out.println("Put " + n);
this.n = n;
}
public int get(){
System.out.println("Got " + n);
return n;
}
}
LockClass:
public class LockClass {
private static Object Lock = new Object();
private LockClass(){
}
public static Object getLock(){
return Lock;
}
}
Verbraucher:
public class Consumer implements Runnable {
Thread t;
Q q;
public Consumer(Q q){
this.q = q;
t = new Thread(this);
t.start();
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized(LockClass.getLock()){
q.get();
}
try {
System.out.println("Consumer slept");
Thread.sleep(1000);
System.out.println("Consumer awake");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Hersteller:
public class Producer implements Runnable {
Q q;
Thread t;
int i;
public Producer(Q q){
this.q = q;
t = new Thread(this);
t.start();
i = 0;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
i++;
synchronized(LockClass.getLock()){
q.put(i);
}
try {
System.out.println("Producer slept");
Thread.sleep(1000);
System.out.println("Producer awake");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
DemoClass: Diese Klasse hat die Hauptfunktion
public class DemoClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Q q = new Q();
Producer prod = new Producer(q);
Consumer cons = new Consumer(q);
}
}
Also, wenn ich diesen obigen Code ausführen, ich so etwas wie dieses:
Put 1
Producer slept
Got 1
Consumer slept
Consumer awake
Producer awake
Got 1
Consumer slept
Put 2
Producer slept
Consumer awake
Producer awake
Got 2
Consumer slept
Put 3
Producer slept
Consumer awake
Producer awake
Got 3
Consumer slept
Put 4
Producer slept
Also, ich mache eigentlich die fädeln Sie den Schlaf in Producer und Consumer ein, damit genug Zeit für den Kontextwechsel bleibt. Wenn nun beide gleichzeitig schlafen müssen, wenn der Produzent zuerst schläft, sollte er zuerst wach werden. Aber wie ich in der Ausgabe sehen kann, schläft der Produzent zuerst, aber immer noch erwacht der Verbraucher zuerst und als welcher Thread zuerst erwacht sollte die Sperre erhalten und so ein anderer Thread warten sollte, bis die Sperre freigegeben wird.
Warum funktioniert es nicht so, wie ich es erwarte? Fehle ich etwas?
Jedes Mal, wenn Sie „Erzeuger“ und „Verbraucher“, das erste, was hören Sie ist ein 'BlockingQueue' denken sollte. Der Erzeuger führt Schleifen durch, indem er Objekte in die Warteschlange legt (die Objekte könnten in diesem Fall "Ganzzahl" -Objekte sein), und der Verbraucher führt Schleifen aus, indem er Objekte herausnimmt. Wenn die Warteschlange leer ist, wenn der Benutzer versucht, ein Objekt zu entfernen, wird der Benutzer blockiert, bis ein Objekt verfügbar wird. Und wenn die Warteschlange eine obere Größenbeschränkung hat (oft eine gute Idee), wird der Produzent blockiert, sobald die Warteschlange voll wird. –
@jameslarge: Vielen Dank! :) Ich werde in eine BlockingQueue schauen –