Java线程,在一个线程运行时挂起多个其他线程

Java线程,在一个线程运行时挂起多个其他线程,java,multithreading,Java,Multithreading,我试图理解我正在做的一部分作业的并发性。我想我已经完成了基本的工作,但是我被困在用例的细微差别中 如果我还没有掌握这个问题的技巧,我提前道歉 基本思想: 我有一个类,其中一些对象被实例化为房屋部分的表示,它们唯一的主要功能是operation()。问题是,当“铃声”响起时,我希望其他人等待()。我的while语句基于钟形开关(布尔值)。如果是on-wait(),如果不是,请继续。似乎在运行这个程序时,为了“Bell”,我正在饥饿其他线程对象 你觉得我哪里出了问题吗 import java.ut

我试图理解我正在做的一部分作业的并发性。我想我已经完成了基本的工作,但是我被困在用例的细微差别中

如果我还没有掌握这个问题的技巧,我提前道歉

基本思想:

我有一个类,其中一些对象被实例化为房屋部分的表示,它们唯一的主要功能是operation()。问题是,当“铃声”响起时,我希望其他人等待()。我的while语句基于钟形开关(布尔值)。如果是on-wait(),如果不是,请继续。似乎在运行这个程序时,为了“Bell”,我正在饥饿其他线程对象

你觉得我哪里出了问题吗

import java.util.ArrayList;
类测试扩展了线程{
静态整数=0;
专用静态最终整数倍=30;
私有静态布尔状态=false;
私有字符串名称;
私人国际旅行社;
测试(字符串y,int x){
数字=数字+1;
val=x;
名称=新字符串(y);
} 
public void run(){//覆盖默认run()
对于(int i=val;i>0;i--){
System.out.println(name+“run():”+i);
操作();
}
}
公共同步无效操作(){
系统输出打印项次(名称+操作);
while(bellstatus){
试一试{
System.out.println(“铃声响起”);
wait();}catch(InterruptedException e){}
}
如果(名称等于(“贝尔”)){
试一试{
系统输出打印(“钟形工作”);
bellstatus=true;
睡眠(500);
Thread.yield();}catch(InterruptedException e){
状态=假;
notifyAll();
System.err.println(“钟声结束”);
}
如果(名称等于(“门”)){
试一试{
系统输出打印(“门加工”);
Thread.sleep(500);}catch(InterruptedException e){
}
if(name.equals(“窗口”)){
试一试{
System.out.println(“窗口工作”);
Thread.sleep(500);}catch(InterruptedException e){
}
}     
公共静态void main(字符串arg[]){
ArrayList示例=新建ArrayList();
试验a=新试验(“钟形”,20);
试验b=新试验(“门”,20);
测试c=新测试(“窗口”,20);//创建线程
示例.添加(a);
示例.添加(b);
示例.添加(c);
System.out.println(“对象数:+a.Number”);

对于(int i=0;i只使用一个线程和一个可运行队列。只有一个线程的执行者将对您的任务进行排队,直到一个运行完成。notifyAll的javadoc提到:

唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个等待方法在对象监视器上等待

但是,
operate
方法正在线程对象的实例上同步。因此,
notifyAll
不会唤醒正在等待的线程,因为每个线程都拥有一个不同的监视器并且正在该监视器上等待

解决此问题的一种方法是在共享锁上同步:

...
static Object lock = new Object();
...

public void operate() {
    synchronized (lock) {

        System.out.println(name + " operating");

        while (bellstatus) {
            try {
                System.out.println("Bell is ringing");
                lock.wait();
            } catch (InterruptedException e) {
            }
        }

        if (name.equals("Bell")) {
            try {
                System.out.println("Bell working");
                bellstatus = true;
                Thread.sleep(500);
                Thread.yield();
            } catch (InterruptedException e) {
            }
            bellstatus = false;
            lock.notifyAll();
            System.err.println("Bell is done");
        }

        if (name.equals("Door")) {
            try {
                System.out.println("Door working");
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
        if (name.equals("Window")) {
            try {
                System.out.println("Window working");
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
    }
}
请不要使用(您可以使用菱形运算符
)。然后,如果我理解您的问题,一个可能的解决方案是使用

静态类测试扩展线程{
静态整数=0;
private static Lock=new ReentrantLock();
私有字符串名称;
私人国际旅行社;
测试(字符串y,整数x){
数字=数字+1;
val=x;
名称=新字符串(y);
}
公开募捐{
对于(int i=val;i>0;i--){
System.out.println(name+“run():”+i);
操作();
}
}
公共同步无效操作(){
System.out.printf(“%s操作%n”,名称);
lock.lock();
试一试{
System.out.printf(“%s工作%n”,名称);
睡眠(500);
System.out.printf(“%s完成%n”,名称);
}捕捉(中断异常e){
e、 printStackTrace();
}最后{
lock.unlock();
}
}
}
公共静态void main(字符串arg[]){
列表示例=新建ArrayList();
试验a=新试验(“钟形”,20);
试验b=新试验(“门”,20);
测试c=新测试(“窗口”,20);//创建线程
示例.添加(a);
示例.添加(b);
示例.添加(c);
System.out.println(“对象数:+a.Number”);
对于(int i=0;i
感谢您向我介绍原始类型-我正在学习Java速成课程-所以我不知道我缺少什么。感谢您查看我的代码。我一直在学习Oracle的Java教程,对可重入锁的工作有一个大致的了解。我的问题是想弄清楚如何才能使其“Bell”是唯一一个可以调用lock/unlock的对象-当Bell运行时,其他对象可以操作。此属性仅适用于Bell。再次感谢您的查看-我将阅读更多内容。嗨,感谢您的查看。我已经尝试了课程教科书中概述的此方法。我的倒计时成功,但我不确定它是否有效“铃响了”这句话是正确的从来没有出现过。我玩过Bell的睡眠设置,设置的时间长了,而其他的时间短了却没有用。我想知道什么是有效的测试方法。再次感谢。嗨,谢谢你看这个。我正在尝试让Bell停止所有其他对象的运行-我不确定队列是什么ant?无论如何,其他两种被建议的方法都在我正在学习的课程范围内,所以我想我会沿着这些思路继续学习。再次感谢您抽出时间来研究。
static class Test extends Thread {
    static int number = 0;

    private static Lock lock = new ReentrantLock();
    private String name;
    private int val;

    Test(String y, int x) {
        number = number + 1;
        val = x;
        name = new String(y);
    }

    public void run() {
        for (int i = val; i > 0; i--) {
            System.out.println(name + " run() : " + i);
            operate();
        }
    }

    public synchronized void operate() {
        System.out.printf("%s operating%n", name);
        lock.lock();
        try {
            System.out.printf("%s working%n", name);
            Thread.sleep(500);
            System.out.printf("%s done%n", name);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public static void main(String arg[]) {
    List<Test> example = new ArrayList<>();
    Test a = new Test("Bell", 20);
    Test b = new Test("Door", 20);
    Test c = new Test("Window", 20);// create thread

    example.add(a);
    example.add(b);
    example.add(c);

    System.out.println("Number of objects: " + a.number);
    for (int i = 0; i < example.size(); i++) {
        example.get(i).start();
    }
    // start thread run
}