主线程创建两个线程 t1 和 t2 run() 方法,这些线程创建两个新线程 c1 和 c2。我想要一个场景,直到c1&c2(的t1)还活着,t2不会开始执行。在我的代码中,通知和等待导致运行时异常。由于它们不在同步块中,如何做到这一点?
public class childTcreat2newthread {
public static void main(String[] args) throws InterruptedException {
Thread mainT=Thread.currentThread();
Target ra=new Target("a");
Thread t1=new Thread(ra);
t1.start();
t1.join();
while(ra.getC1().isAlive()==true||ra.getC2().isAlive()==true){
synchronized (mainT) {
mainT.wait();
}}
new Thread(new Target("b")).start();}}
class Target implements Runnable{
Thread c1=new Thread(new Target1("1"));
Thread c2=new Thread(new Target1("2"));
String msg;
Target(String msg){
this.msg=msg;
}
@Override
public void run() {
for(int j=0;j<100000;j++){
for(int i=0;i<10000;i++){
if(i%10000==0&&j%10000==0){System.out.print(msg);}
}}
t1.start();
t2.start();
}
public Thread getC1(){return c1;}
public Thread getC2(){return c2;}
}
class Target1 implements Runnable {
String msg;
Target1(String msg){
this.msg=msg;
}
@Override
public synchronized void run() {
for(int j=0;j<100000;j++){
for(int i=0;i<100000;i++){
if(i%100000==0&&j%10000==0){System.out.print(msg);}
}
}
try{
notifyAll();
System.out.println("K");}catch(IllegalMonitorStateException e){System.out.println("nIllegalMonitorStateException!! in "+msg+"n");}
}
}
wait( ) 告诉调用线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用 notify( )。呼叫通知时无法获得相同的监视器。怎么做?
至于我的理解,线程 t1 和 t2 在这里都没有它们正在访问的公共对象,所以我们应该在同步锁中传递哪个对象来调用 wait() 和 notify()?
@JB Nizet指出的那样,你应该使用join来等待线程终止
编辑由于您不能使用join,因此建议您使用CountDownLatch,因为其文件指出:
一种同步辅助工具,它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
这就是你要求的。
第二次编辑
下面是代码的修改版本,它使用使用等待和通知的自制 CountDownLatch 等待线程终止。
import java.util.concurrent.CountDownLatch;
public class childTcreat2newthread {
public static void main(String[] args) throws InterruptedException {
MyCountDownLatch doneSignal = new MyCountDownLatch(2);
Target ra = new Target("a",doneSignal);
Thread t1 = new Thread(ra);
t1.start();
doneSignal.await();
System.out.println("after await ");
MyCountDownLatch doneSignal1 = new MyCountDownLatch(2);
new Thread(new Target("b",doneSignal1)).start();
}
}
class Target implements Runnable {
private Thread c1;
private Thread c2;
String msg;
Target(String msg, MyCountDownLatch doneSignal) {
this.msg = msg;
c1 = new Thread(new Target1("1",doneSignal));
c2 = new Thread(new Target1("2",doneSignal));
}
@Override
public void run() {
System.out.println("Start of Target " + msg);
for (int j = 0; j < 100000; j++) {
for (int i = 0; i < 10000; i++) {
if (i % 10000 == 0 && j % 10000 == 0) {
System.out.print(msg);
}
}
}
c1.start();
c2.start();
// try {
// c1.join();
// c2.join();
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
System.out.println("End of Target " + msg);
}
public Thread getC1() {
return c1;
}
public Thread getC2() {
return c2;
}
}
class Target1 implements Runnable {
String msg;
private MyCountDownLatch doneSignal;
Target1(String msg, MyCountDownLatch doneSignal) {
this.msg = msg;
this.doneSignal=doneSignal;
}
@Override
public void run() {
System.out.println("Start of Target1 " + msg);
for (int j = 0; j < 100000; j++) {
for (int i = 0; i < 100000; i++) {
if (i % 100000 == 0 && j % 10000 == 0) {
System.out.print(msg);
}
}
}
try {
System.out.println("K");
doneSignal.countDown();
System.out.println("End of Target1 " + msg);
} catch (IllegalMonitorStateException e) {
System.out.println("nIllegalMonitorStateException!! in " + msg
+ "n");
}
}
}
class MyCountDownLatch {
private int waitersNum;
public MyCountDownLatch(int waitersNum) {
this.waitersNum=waitersNum;
}
public synchronized void countDown() {
waitersNum--;
if (waitersNum==0) {
notifyAll();
}
}
public synchronized void await() throws InterruptedException {
wait();
}
}
通知、通知所有、等待调用应在同一对象的监视器中完成。应该有一个像Object
这样的共享对象,你应该围绕它构建你的逻辑。例如:
public class ClassA{
Object lockObject=new Object();
//Thread A will call this method
public void methodA(){
synchronized(lockObject){
while(!aCondition)
lockObject.wait();
}
}
//Thread B will call this method
public void methodB(){
synchronized(lockObject){
aCondition=true;
lockObject.notify();
}
}
}