[英]Java Thread Wait-Notify
我有3個線程(A,B,C),只是我無法使它們按我希望的那樣工作。 所有這3個線程共享對同一對象-K的引用。我正在嘗試啟動所有3個線程,然后在線程A到達某種狀態的某個時間點,暫停線程B和C,直到A執行一些方法work(),當工作完成時,繼續B和C。
現在,我在代碼中有了:線程A同時引用了B和C。B和C具有方法pause(){Synchronized(K){k.wait; }}當A到達某個狀態時,我從FROM的run()方法調用:B.pause(),C.pause()。 現在我期望的是線程B和C將一直等待,直到有人執行以下操作:k.notifyAll(),但線程A停止了。 這在Java中正常嗎?
碼:
class A implements Runnable {
private K k;
private B b;
private C c;
void run() {
while(something) {
//do something
b.pause();
c.pause();
// !!! here this thread will freeze and doSomething2 wont get executed.
// what i want is to pause B, C, doSomething2 to get executed and then resume B and C
//do something2
synchronized(k) {
k.notifyAll();
}
}
}
}
class B implements Runnable {
private K k;
void run() {
while(something) {
//dome something
}
}
}
public pause() {
synchronized(k) { k.wait();}
}
}
class C implements Runnable {
private K k;
void run() {
while(something) {
//dome something
}
}
}
public pause() {
synchronized(k) { k.wait();}
}
}
您可以使用CylcicBarrier來實現這一點。
CyclicBarrier barrier = new CyclicBarrier();
public void run() {
new Thread(new A(barrier)).start();
new Thread(new B(barrier)).start();
barrier.await(); // Waits until all threads have called await()
// Do something
}
public void A implements Runnable {
private CyclicBarrier barrier;
public A(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
barrier.await();
// Do something.
}
}
public void B implements Runnable {
private CyclicBarrier barrier;
public B(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
barrier.await();
// Do something.
}
}
當您調用B.pause()時,它是在本地線程中執行的,而不是在您調用B的run方法的線程中執行的。Thread類上有一些不贊成使用的方法,但是這樣做很危險,請參見此處: http ://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
您確定調用b.pause()但聲明B.sleep()嗎?
很高興看到線程的構造/啟動代碼。
您知道您正在使用3個不同的對象(監視器)Ak,Bk,Ck嗎?
因此,當B“暫停”時,它會在自己的監視器(Bk)上同步,該監視器無論如何都應該是空閑的。 您的線程不會以任何方式“通信”。
取下調用b.pause()
和c.pause()
從A.run()
並從自己的運行方法調用它們。
除非我對您的家庭作業有誤解,否則我認為您需要做的是學習如何中斷線程。 B和C是可中斷線程,需要以這樣的方式處理中斷:它們直到被告知可以正常執行后才能恢復。 它可能看起來像這樣:
while(true)
{
try
{
Thread.sleep(100);
System.out.println("Thread is working normally...");
}
catch(InterruptedException e)
{
System.out.println("Thread has been interrupted, will wait till A is done...");
try
{
synchronized(monitor)
{
monitor.wait();
}
}
catch(InterruptedException e2)
{
// whatever...
}
}
}
因此,在其自己的線程中運行的對象A將引用其他兩個線程。 對象A將有權訪問共享監視對象,其他兩個線程中的可運行對象也可以訪問該共享監視對象(我稱它為monitor
)。 當A中斷其他線程時,它們的可運行對象將在監視器上調用wait()
。 完成A后,它將在監視器上調用notifyAll()
。 注意您也應該清除其他線程中的中斷標志,但是我讓您自己弄清楚-這很容易:)
我通常不會在這個細節上幫助家庭作業,但是我認為您無論如何都使用了錯誤的方法,因此我認為幫助您做您幾乎肯定不應該做的事情沒有害處:)
class A implements Runnable {
private K k;
private B b;
private C c;
void run() {
while(something) {
//do something
b.pause();
c.pause();
// !!! here this thread will freeze and doSomething2 wont get executed.
// what i want is to pause B, C, doSomething2 to get executed and then resume B and C
//do something2
synchronized(k) {
k.notifyAll();
}
}
}
}
class B implements Runnable {
private K k;
volatile boolean isPaused = false;
void run() {
while(something) {
if (isPaused) {
synchronized(k) { k.wait();}
isPaused = false;
}
//dome something
}
}
public pause() {
isPaused = true;
}
}
class C implements Runnable {
private K k;
volatile boolean isPaused = false;
void run() {
while(something) {
if (isPaused) {
synchronized(k) {
k.wait();
}
isPaused = false;
}
//dome something
}
}
public pause() {
isPaused = true;
}
}
我猜想您實際上想要做的是無條件地在B
和C
k
上等待,然后總是在A
調用notifyAll
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.