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

时间:2014-11-12 20:37:06

标签: java multithreading

我正在努力理解我正在做的任务的部分并发性。我想我已经完成了基础知识,但是我已经陷入了我的用例的细微差别。

如果我还没有掌握这个问题的艺术,我会提前道歉。

基本理念:

我有一个类,其中一些对象被实例化为房屋部分的表示,它们唯一的主要功能是操作()。问题是,当“贝尔”运作时,我希望其他人等待()。我的while语句基于铃声切换(布尔值)。如果它打开 - 等待(),如果没有,继续。似乎在运行这个程序时,我为了“Bell”而挨饿其他螺纹对象。

关于我哪里出错了?

import java.util.ArrayList;

class Test extends Thread { 
  static int number = 0;
  private static final int TIMES = 30; 
  private static boolean bellstatus = false;
  private String name;
  private int val; 
 
   Test(String y,int x) { 
    number = number +1;
     val = x;
    name = new String(y);
  } 
  public void run() { // overrides default run() 
   
    for (int i=val; i>0; i--){ 
      System.out.println(name+" run() : " + i);
      operate();
    }
  }
  
  public synchronized void operate(){
   System.out.println(name+ " operating");
  
   while(bellstatus){
     try{
     System.out.println("Bell is ringing");
     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;
     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){}
  }
  }     
  

  
  
public static void main(String arg[]) { 
   ArrayList<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 
    
}
}

3 个答案:

答案 0 :(得分:1)

只使用一个线程和一个runnables队列。只有一个线程的执行程序会将您的任务排队,直到完成一个任务https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html

答案 1 :(得分:1)

请不要使用Raw Types(您可以使用钻石运营商<>)。然后,如果我理解你的问题,一个可能的解决方案是使用ReentrantLock之类的,

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
}

答案 2 :(得分:0)

notifyAll的javadoc提及:

  

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

但是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) {
            }
        }
    }
}