本帖最后由 younerest 于 2011-08-08 12:01:45 编辑

解决方案 »

  1.   

    notifyAll必须是syncronized中的对象才能使用
    所以从你的程序来看,应该是
    runname.notifyAll(); 
      

  2.   


    改成runname.notifyAll();后也还是不行
      

  3.   

    改成runname.notifyAll(); 然后把这两个new SequenchThread("B").start();new SequenchThread("C").start();
    注释掉,你运行程序看看,与notifyAll();对比。
    主要是你写的逻辑有点乱啊,你用notifyAll()去唤醒别人的时候,别人只能是同一个锁下的wait(),所以你这种思路不太行啊。
    你看看这个http://hi.baidu.com/dapplehou/blog/item/14e62834ebe1bc235ab5f504.html
      

  4.   

    java.lang.IllegalMonitorStateException
    抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 notifyAll抛出的原因
    IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。第一,不是同一个锁对象的时候,会抛出来
    第二,当锁对象之前没有wait的线程的时候,也会抛出来
      

  5.   

    我稍做了点修改:package test;import java.util.ArrayList;public class SequenchThread extends Thread{
     static ArrayList<String> namelist=new ArrayList<String>();
    static String runname="";
    public String name;
    public int printcount=0;
    static int waitcount=0;
    public String GetName()
    {
    return name;
    }
    public SequenchThread(String name)
    {
    this.name=name;
    namelist.add(name);
    synchronized(runname){
    if (runname.equals(""))
    runname=name;
    }
    }
    public void run()

    while(true)
    {
    synchronized(runname)
    {
    System.out.println("thread"+name+"is running");
    if(runname.equals(GetName())){
    System.out.println("打印"+GetName());
    int j=0;
    while(!namelist.get(j).equals(runname))
    {
    j++;
    }
    j++;
    if(j==namelist.size())
    j=0;
    runname=namelist.get(j);
    printcount++;
    if(waitcount>0)
    {
    runname.notifyAll();
    System.out.println("唤醒所有线程");
    waitcount=0;
    }
    }else{
    try{
    System.out.println("thread"+name+"is wait");
            waitcount++;
    runname.wait();
    System.out.println("thread"+name+"  is awake");
    }catch(InterruptedException e)
    {}
    }


    }
    /* try{
    sleep(3000);
    }catch(InterruptedException e2)
    {}*/

    if(printcount==10)
    break;
    System.out.println("the name of the thread for the next running is  "+runname);


    }

    }public static void main(String args[])
    {
    new SequenchThread("A").start();
    new SequenchThread("B").start();
    new SequenchThread("C").start();

    }}
     
    运行结果如下:
    threadAis running
    打印A
    the name of the thread for the next running is  B
    threadAis running
    threadAis wait    等待
    threadBis running
    打印B
    threadCis running
    打印C
    Exception in thread "Thread-2" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at test.SequenchThread.run(SequenchThread.java:45)
    Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at test.SequenchThread.run(SequenchThread.java:45)我现在想问西,为什么在线程A等待的时候调用,线程C调用notifyAll会出错。
      

  6.   

    不说这么说的,线程在运行的时候,你根本不知道先后顺序,有可能连续运行了2次同一条线程方法体,而其他的线程没运行,所以就会导致报错,而且notifyAll意思是,对于所有线程在此对象上有锁的都唤醒,然后再去竞争,竞争同时有可能A线程会导致B线程再次wait
      

  7.   

    不过我这程序的问题是出在notifyAll,照你之前的说法,这可能是没有线程在wait,不过我修改后的程序至少有一个线程在wait,在这种情况下也报错所以我也很迷惑。
      

  8.   

    有可能连续运行了2次同一条线程方法体,就是运行了2次循环。。换句话说,调用了2次notifyAll,可能第一次能做释放,可第二次就没了,不过这个压根不能确定,不过可以肯定的是,调用notifyAll的时候,没线程在该对象上等待
      

  9.   

    3楼说的。逻辑有点乱,不过我说的不是你想的逻辑,是程序的可以建议看看这个http://zhangjunhd.blog.51cto.com/113473/71387,然后再想想
      

  10.   

    你的这个runname赋值不断变化,就不要拿来做锁
    每次给runname赋值,那么这个runname的具体对象都会改变
    所以虽然synchronized(runname)中用runname做锁,但是三个线程的锁都不同,所以报异常
    这个结果应该满意了吧?
      

  11.   

    自己终于搞定了,原来进程锁的值不能改变。package test;import java.util.ArrayList;public class SequenchThread extends Thread{
    public  static ArrayList<String> namelist=new ArrayList<String>();
    public static String runname="";
    public static String runname2="str";//修改public String name;
    public int printcount=0;
    static int waitcount=0;
    public String GetName()
    {
    return name;
    }
    public SequenchThread(String name)
    {
    this.name=name;
    namelist.add(name);
    synchronized(runname2){
    if (runname.equals(""))
    runname=name;
    }
    }
    public void run()

    while(true)
    {
    synchronized(runname2) //修改 {
    System.out.println("thread "+name+" is running");
    if(runname.equals(GetName())){
    System.out.println("打印"+GetName());
    int j=0;
    while(!namelist.get(j).equals(runname))
    {
    j++;
    }
    j++;
    if(j==namelist.size())
    j=0;
    runname=namelist.get(j);
    printcount++;
    if(waitcount>0)
    {
    runname2.notifyAll(); //修改 System.out.println("唤醒所有线程");
    waitcount=0;
    }
    }else{
    try{
    System.out.println("thread"+name+"is wait");
            waitcount++;
    runname2.wait();  //修改 System.out.println("thread"+name+"  is awake");
    }catch(InterruptedException e)
    {}
    }


    }
    /* try{
    sleep(3000);
    }catch(InterruptedException e2)
    {}*/

    if(printcount==10)
    break;
    System.out.println("the name of the thread for the next running is  "+runname);


    }

    }public static void main(String args[])
    {
    new SequenchThread("A").start();
    new SequenchThread("B").start();
    new SequenchThread("C").start();

    }}