新人庸人自扰,纠结此问题数日,求高人明示。请问高人,JAVA里面有没得啥子办法把一个子线程暂停,然后返回主线程执行另外一个子线程,然后另外一个子线程又暂停,继续执行先前那个被暂停的子线程(此时第一个子线程接着执行完被暂停时未执行完的代码),等第一个子线程执行完了,再接着执行完被暂停的第二个子线程(同理,这第二个子线程也是继续执行刚被挂起前未被执行完的代码),然后返回主线程继续执行主线程的代码。注: 第一个子线程和第二个子线程都是非循环执行的,也就是说,第一个子线程和第二个子线程只执行一次。就是说怎么暂停一个正在执行代码的子线程,并且让其恢复后,接着执行剩下的代码,而不是又重头执行一次,我意思是只接着执行因为暂停而未执行的剩下那部分的代码。谢谢高人解答,困惑我许久啊!!! (sleep尝试过,但是貌似那个太不可控,往往是第一个子线程醒来第二个还没开始执行。我就想了解下如何用可控的手段,让两个并发的子线程,通过主线程中转,互相暂停各自的一部分,然后接着执行各自剩下的一部分)唉,用语不太科学准确,还请高人海涵。谢谢!

解决方案 »

  1.   

    试试Thread.yield();
    yield() 
    暂停当前正在执行的线程对象,并执行其他线程
      

  2.   

    子线程里面运行到判断部分,sleep一小段,检查一个标志flag,如果被对方线程修改了,就往后顺序执行下去,否则继续sleep,一会再来检查
    此flag来自主线程里面一个public static。不知道得行不?
      

  3.   

    利用线程同步应该可以的吧
    第一个线程运行一会,然后sleep,同时notifyAll其他线程
    第二个线程运行一会后也sleep,同时notifyAll第一个线程
    第一个线程继续运行,结束时notifyAll第二个线程
      

  4.   

    synchronized关键字可以实现两个线程同步一个主线程的变量Object syncObj = new Object(),在第一线程的同步块中syncObj.wait(),syncObj.notifyAll()以后第二个线程才能进入同步块中,然后使用同样的方法回到第一线程的同步块中。建议楼主好好看看java的线程同步、sychronized方面的内容。
      

  5.   

    晕,应该是wait吧,sleep根本就没有释放执行权,时间一到就继续执行了,老大,别误导人家
      

  6.   

    研究这2个东西java.lang.Object.wait()  java.lang.Object.notify()
      

  7.   

    对的 就是 wait 和 notify or notifyAll
      

  8.   

    子线程调用wait()过后确实是让出了锁,暂停了,但是当主线程试图返回这个子线程的时候,这个子线程又从头开始执行了。。我尝试过两个子线程互相嵌套wait(), notify()的方法,但我发现,在一个子线程中开始唤醒另一个子线程是可以的:比如(thread) b {
     
                  (thread)a.start() }
    这个是没问题的,但是,如果试图在b里面调用 a.wait() ,即阻塞b线程来执行a线程的代码就会出错
    我查了信息,发现主线程是可以通过调用:   main thread{     a.wait() ;} 来使a 中断主线程来执行a这个子线程的代码,然后待a子线程执行完它的代码后再返回主线程。我尝试将以上思想反过来用,即:thread a {
             wait();
              ....
              ....
    }
    我想 中断a子线程,然后返回执行主线程,但是这样就死锁了。。a这个子线程一自我wait()就回不去了,自己把自己搞死了。。
    看来这种思路不能反起用,那么,JAVA里面有什么机制能够实现子线程自我调用或者其他线程调用方法来暂停它,转而执行其他线程,然后还能够醒过来 接着“执行暂停前未执行的代码”(非重新开始执行)还是困惑不已啊
    再次感谢楼上的这些热心高人,祝福你们!
      

  9.   

    wait 会在那里等着,等到被其他线程唤醒的时候就会继续执行下面的代码啊
      

  10.   

    楼上这位大哥,我试过,我发现 假如 a 子线程 wait()了, 然后,主线程继续执行并且中断来执行子线程b, a,b是平级关系,然后子线程b执行到最后调用 notifyAll(),本来我以为这样可以唤醒a子线程 继续执行完剩下的代码,但是似乎唤不醒也不起作用,给我的感觉就是a线程就这么结束了主线程继续执行,想调用a可以,但是就是重头执行a线程了。。 
      

  11.   

    我帖点代码来说明下这个问题,请专家指点其中的错误:
    首先是尝试在子线程c中调用b.wait() 来使b中断线程c的执行,转而执行线程b
    (thread)c
    {
    synchronized(this){

     System.out.println("this is threadC");

       try
         {b.start();
       System.out.println("Waiting for c to run...");
       b.wait(); 
              System.out.println("C has Completed.Now back to main thread");
            }catch (InterruptedException e){e.printStackTrace();}
            notifyAll();
      }
    然后我执行线程b ,希望通过线程b的执行完成来唤醒线程c(thread)b
      {
        synchronized(this)
        {  
         System.out.println("thread b"+"is waking up"); 
        
          System.out.println("ThreadB is running..");
          
     
          notifyAll();
        }
      }
    }得到的结果是, b线程确实执行完了,C线程也确实在b.wait()处暂停了,但是,b线程调用的notifyAll()并没有唤醒阻塞状态的c,而是继续返回执行主线程,就是说c没有继续执行下去。并且还报错: at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:485)
    at ThreadC.run(ThreadC.java:23) //这个位置就是b.wait() 这句话的位置。
      

  12.   

    你在 C 线程中使用的对象锁不正确。应该把 C 中的 synchronized(this) 改为 synchronized(b),也就是把 b 对象作为锁,因为使用的是 b.wait(),因此也必须使用 b 作为对象锁。更改后的代码如下:public class NotifyWaitTest {    public static void main(String[] args) {
            Thread c = new Thread(new ThreadC());
            c.start();
        }
    }class ThreadC implements Runnable {    public void run() {        Thread b = new Thread(new ThreadB());        // 以对象 b 作为锁,这里的对象 b 也就是在 ThreadB 线程中 this 对象
            synchronized (b) {
                System.out.println("this is threadC");            // 启动 b 线程,由于 b 线程中使用 this,也就是这个 b 对象作为锁,因此 b.start()
                // 中的代码并不会马上执行,而需要等待到这个线程将 b 对象锁释放掉
                b.start();            System.out.println("Waiting for c to run...");
                try {                // 在 b 对象锁上进行等待,等待的同时将 b 锁释放给其他线程用,此时 C 线程在此一直阻塞。
                    // 当在其他线程中执行了 b.notifyAll() 时会将其唤醒,该线程会等待 b 对象锁重新锁定代码块,
                    // 执行下面的代码
                    b.wait();                System.out.println("C has Completed.Now back to main thread");
                } catch (InterruptedException e) {
                    // // 可能在什么地方执行了 Thread.currentThread().interrpt() 方法会抛出此异常
                    e.printStackTrace();
                }
            }
        }
    }class ThreadB implements Runnable {    @Override
        public void run() {        // 使用当前对象作为锁,锁住代码块
            // 被锁住的代码只能在 C 线程中释放了 b 对象锁(执行到 b.waite() 方法后),这里才有机会执行,
            synchronized (this) {
                System.out.println("thread b is waking up");
                System.out.println("ThreadB is running..");            // 唤醒所有在这个对象上等待的线程
                // 当然了,要其他等待着的线程运行,需要这个线程运行完后释放当前对象锁,其他等待
                // 中的线程才有机会重新获得这个对象的锁
                notifyAll();            System.out.println("after ThreadB notifyAll");
            }
        }
    }
      

  13.   

    一般来说不大会把线程对象作为对象锁来使用,我们可以 new 一个 Object 来作为对象锁
      

  14.   

    谢谢 bao110908 这位高人!!! 一语点醒梦中人啊!!! 太感谢了,还帮我写了这么多代码注释,感动ing!
    祝福这位好心的大哥!好人一生平安,事业有成!!
      

  15.   

    之所以你前面写的代码会抛出异常,是因为:代码中使用的是 b.wait(); 在执行这行代码时,JVM 会释放将 b 对象的锁,但是你的代码中并不是用 b 作为对象锁的,而是使用当前对象作为对象锁的,在这段代码中根本就没有用到 b 对象锁,因此就会抛出这个异常。通过 Object#wait() 方法的 API DOC,在抛出异常(IllegalMonitorStateException)说明部分会有说明:如果当前的线程不是此对象监视器的所有者
      

  16.   

    唉,我这么搞在试验也是被逼无奈,我有一个作业就是讲什么学生等老师上课,老师上课的时候学生只能在外面等老师下课,老师下课了学生才能进教室上课,饶来绕去,我就自己归纳出是两个线程交互的问题唉
    再次感谢bao110908大哥!
      

  17.   

    代码中使用的是 b.wait(); 在执行这行代码时,JVM 会释放将 b 对象的锁,但是你的代码中并不是用 b 作为对象锁的,而是使用当前对象作为对象锁的,在这段代码中根本就没有用到 b 对象锁,因此就会抛出这个异常。-----------------------
    大哥所言甚是,当时我用synchronized (this),是想的是如果多个线程同时在执行这段代码的时候,只能当前的一个线程拿到锁,没想到如果后面指定了是b调用wait(),前面synchronized () 就要变成synchronized (b)纠结了这么多天的问题啊。看来凡事都该上上CSDN问,还是好人多啊。哈哈