java多线程中,其中一个子线程暂停返回的问题

sansoar 2010-04-24 11:22:42
新人庸人自扰,纠结此问题数日,求高人明示。

请问高人,JAVA里面有没得啥子办法把一个子线程暂停,然后返回主线程执行另外一个子线程,然后另外一个子线程又暂停,继续执行先前那个被暂停的子线程(此时第一个子线程接着执行完被暂停时未执行完的代码),等第一个子线程执行完了,再接着执行完被暂停的第二个子线程(同理,这第二个子线程也是继续执行刚被挂起前未被执行完的代码),然后返回主线程继续执行主线程的代码。

注: 第一个子线程和第二个子线程都是非循环执行的,也就是说,第一个子线程和第二个子线程只执行一次。就是说怎么暂停一个正在执行代码的子线程,并且让其恢复后,接着执行剩下的代码,而不是又重头执行一次,我意思是只接着执行因为暂停而未执行的剩下那部分的代码。

谢谢高人解答,困惑我许久啊!!!

(sleep尝试过,但是貌似那个太不可控,往往是第一个子线程醒来第二个还没开始执行。我就想了解下如何用可控的手段,让两个并发的子线程,通过主线程中转,互相暂停各自的一部分,然后接着执行各自剩下的一部分)

唉,用语不太科学准确,还请高人海涵。谢谢!
...全文
1070 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
iori200908 2010-04-24
  • 打赏
  • 举报
回复
synchronized关键字可以实现

两个线程同步一个主线程的变量Object syncObj = new Object(),在第一线程的同步块中syncObj.wait(),syncObj.notifyAll()以后第二个线程才能进入同步块中,然后使用同样的方法回到第一线程的同步块中。

建议楼主好好看看java的线程同步、sychronized方面的内容。
zfq642773391 2010-04-24
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 qybao 的回复:]
利用线程同步应该可以的吧
第一个线程运行一会,然后sleep,同时notifyAll其他线程
第二个线程运行一会后也sleep,同时notifyAll第一个线程
第一个线程继续运行,结束时notifyAll第二个线程
[/Quote]
up!
sansoar 2010-04-24
  • 打赏
  • 举报
回复
谢谢楼上几个高人,我去试试!祝福你们这些热心人!!!
qybao 2010-04-24
  • 打赏
  • 举报
回复
利用线程同步应该可以的吧
第一个线程运行一会,然后sleep,同时notifyAll其他线程
第二个线程运行一会后也sleep,同时notifyAll第一个线程
第一个线程继续运行,结束时notifyAll第二个线程
eggno8 2010-04-24
  • 打赏
  • 举报
回复
子线程里面运行到判断部分,sleep一小段,检查一个标志flag,如果被对方线程修改了,就往后顺序执行下去,否则继续sleep,一会再来检查
此flag来自主线程里面一个public static。不知道得行不?
sansoar 2010-04-24
  • 打赏
  • 举报
回复
谢谢楼上这位热心人,你说的方法我用过,用了那个子线程就回不来了,倒是可以回到主线程。但是如果主线程再调用这个“被挂起”的子线程,就会重复运行这个子线程了,而不是接着执行子线程之前未执行的代码。
zfq642773391 2010-04-24
  • 打赏
  • 举报
回复
试试Thread.yield();
yield()
暂停当前正在执行的线程对象,并执行其他线程
jbz001 2010-04-24
  • 打赏
  • 举报
回复
这个一点也不难啊~!
lw20746633 2010-04-24
  • 打赏
  • 举报
回复
这个不错
xiaocainiaoyuan 2010-04-24
  • 打赏
  • 举报
回复
学习了....
sansoar 2010-04-24
  • 打赏
  • 举报
回复
代码中使用的是 b.wait(); 在执行这行代码时,JVM 会释放将 b 对象的锁,但是你的代码中并不是用 b 作为对象锁的,而是使用当前对象作为对象锁的,在这段代码中根本就没有用到 b 对象锁,因此就会抛出这个异常。

-----------------------
大哥所言甚是,当时我用synchronized (this),是想的是如果多个线程同时在执行这段代码的时候,只能当前的一个线程拿到锁,没想到如果后面指定了是b调用wait(),前面synchronized () 就要变成synchronized (b)

纠结了这么多天的问题啊。。。。看来凡事都该上上CSDN问,还是好人多啊。。。。哈哈
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 sansoar 的回复:]
谢谢 bao110908 这位高人!!! 一语点醒梦中人啊!!! 太感谢了,还帮我写了这么多代码注释,感动ing!
祝福这位好心的大哥!好人一生平安,事业有成!!
[/Quote]

谢谢了,不用客气,呵呵 :-)
sansoar 2010-04-24
  • 打赏
  • 举报
回复
唉,我这么搞在试验也是被逼无奈,我有一个作业就是讲什么学生等老师上课,老师上课的时候学生只能在外面等老师下课,老师下课了学生才能进教室上课,饶来绕去,我就自己归纳出是两个线程交互的问题。。。唉
再次感谢bao110908大哥!
  • 打赏
  • 举报
回复
之所以你前面写的代码会抛出异常,是因为:

代码中使用的是 b.wait(); 在执行这行代码时,JVM 会释放将 b 对象的锁,但是你的代码中并不是用 b 作为对象锁的,而是使用当前对象作为对象锁的,在这段代码中根本就没有用到 b 对象锁,因此就会抛出这个异常。

通过 Object#wait() 方法的 API DOC,在抛出异常(IllegalMonitorStateException)说明部分会有说明:如果当前的线程不是此对象监视器的所有者
sansoar 2010-04-24
  • 打赏
  • 举报
回复
谢谢 bao110908 这位高人!!! 一语点醒梦中人啊!!! 太感谢了,还帮我写了这么多代码注释,感动ing!
祝福这位好心的大哥!好人一生平安,事业有成!!
  • 打赏
  • 举报
回复
一般来说不大会把线程对象作为对象锁来使用,我们可以 new 一个 Object 来作为对象锁
  • 打赏
  • 举报
回复
你在 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");
}
}
}
liren2 2010-04-24
  • 打赏
  • 举报
回复
学习中...
sansoar 2010-04-24
  • 打赏
  • 举报
回复
我帖点代码来说明下这个问题,请专家指点其中的错误:
首先是尝试在子线程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() 这句话的位置。
sansoar 2010-04-24
  • 打赏
  • 举报
回复
楼上这位大哥,我试过,我发现 假如 a 子线程 wait()了, 然后,主线程继续执行并且中断来执行子线程b, a,b是平级关系,然后子线程b执行到最后调用 notifyAll(),本来我以为这样可以唤醒a子线程 继续执行完剩下的代码,但是似乎唤不醒也。。。不起作用,给我的感觉就是a线程就这么结束了。。。主线程继续执行,想调用a可以,但是就是重头执行a线程了。。
加载更多回复(6)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧