首页 > 编程知识 正文

java入门之线程唤醒与阻塞(java中如何唤醒一个阻塞的线程)

时间:2023-12-02 11:48:12 阅读:311246 作者:MRDT

本文目录一览:

  • 1、java线程阻塞问题,怎么解决
  • 2、Java多线程: 如何阻塞和继续线程运行 (转)
  • 3、如何让线程阻塞,如何唤醒线程,说说不同的唤醒线程方法的区别
  • 4、java 线程释放读写锁时候会唤醒被阻塞的线程么
  • 5、JAVA中,线程有哪五个基本状态?他们之间如何让转化?并简述线程周期。

java线程阻塞问题,怎么解决

典型地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用 resume() 使其恢复。但suspend()方法很容易引起死锁问题,已经不推荐使用了。wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。 初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则相反。 上述的核心区别导致了一系列的细节上的区别。 首先,前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类,也就是说,所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。 其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在 synchronized 方法或块中当前线程才占有锁,才有锁可以释放。同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException 异常。 wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。 关于 wait() 和 notify() 方法最后再说明两点: 第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。 第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。 谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小心地避免死锁。 以上我们对 Java 中实现线程阻塞的各种方法作了一番分析,我们重点分析了 wait() 和 notify() 方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用中我们应该灵活使用各种方法,以便更好地达到我们的目的。

Java多线程: 如何阻塞和继续线程运行 (转)

楼主怕是理解上有些错误。并不是说主进程与子线程的表现形式。

main()是主进程,在一个进程中可以有多个线程。

正确的代码这样写你可能就更容易理解了。

public

class

test

{

public

static

void

main(string[]

args)

{

for

(int

i

=

1;

i

10;

i++)

{

system.out.println("main函数正在运行");

new

testthread().start();

}

}

}

class

testthread

extends

thread

{

public

void

run()

{

while

(!interrupted())

for

(int

i

=

0;

i

10;

i++)

{

system.out.println("thread函数正在运行"+getid());

try

{

sleep(1000);

}

catch

(interruptedexception

e)

{

}

}

}

}

如何让线程阻塞,如何唤醒线程,说说不同的唤醒线程方法的区别

sleep() 方法:

sleep(…毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞状态,期间得不到cpu的时间片,等到时间过去了,线程重新进入可执行状态。(暂停线程,不会释放锁)

suspend() 和 resume() 方法:。

挂起和唤醒线程,suspend()使线程进入阻塞状态,只有对应的resume()被调用的时候,线程才会进入可执行状态。(不建议用,容易发生死锁)

yield() 方法:

会使的线程放弃当前分得的cpu时间片,但此时线程任然处于可执行状态,随时可以再次分得cpu时间片。yield()方法只能使同优先级的线程有执行的机会。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。(暂停当前正在执行的线程,并执行其他线程,且让出的时间不可知)

wait() 和 notify() 方法:

两个方法搭配使用,wait()使线程进入阻塞状态,调用notify()时,线程进入可执行状态。wait()内可加或不加参数,加参数时是以毫秒为单位,当到了指定时间或调用notify()方法时,进入可执行状态。(属于Object类,而不属于Thread类,wait( )会先释放锁住的对象,然后再执行等待的动作。由于wait( )所等待的对象必须先锁住,因此,它只能用在同步化程序段或者同步化方法内,否则,会抛出异常IllegalMonitorStateException.)

join()方法

也叫线程加入。是当前线程A调用另一个线程B的join()方法,当前线程转A入阻塞状态,直到线程B运行结束,线程A才由阻塞状态转为可执行状态。

java 线程释放读写锁时候会唤醒被阻塞的线程么

线程的阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题。如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节。在Java发展史上曾经使用suspend()、resume()方法对于线程进行阻塞唤醒,但随之出现很多问题,比较典型的还是死锁问题。如下代码,主要的逻辑代码是主线程启动线程mt一段时间后尝试使用suspend()让线程挂起,最后使用resume()恢复线程。但现实并不如愿,执行到suspend()时将一直卡住,你等不来“canyou get here?”的输出。

public class ThreadSuspend {

public static voidmain(String[] args) {

Thread mt = newMyThread();

mt.start();

try {

Thread.currentThread().sleep(100);

} catch(InterruptedException e) {

e.printStackTrace();

}

mt.suspend();

System.out.println("canyou get here?");

mt.resume();

}

static class MyThreadextends Thread {

public void run() {

while (true) {

System.out.println("running....");

}

}

}

}

JAVA中,线程有哪五个基本状态?他们之间如何让转化?并简述线程周期。

java中,每个线程都需经历新生、就绪、运行、阻塞和死亡五种状态,线程从新生到死亡的状态变化称为生命周期。

用new运算符和Thread类或其子类建立一个线程对象后,该线程就处于新生状态。

线程的生命周期,把图转化为文字就是: 

1、线程通过new方法创建,调用start,线程进入就绪状态,等待系统的调度(时间片轮转调度)。当系统调度,进入运行状态。正常结束或者异常退出,进程进入死亡状态。

2、处于运行状态的线程若遇到sleep,则线程进入睡眠状态,不会让出资源锁,sleep结束,线程转为就绪状态,等待系统重新调度。

3、处于运行状态的线程可能在等待io,也可能进入挂起状态。io完成,转为就绪状态。

4、处于运行状态的线程yield,线程转为就绪状态。(yield只让给权限比自己高的)

5、处于运行状态的线程遇到wait,线程处于等待状态,需要notify()/notifyALL来唤醒线程,唤醒后的线程处于锁定状态,获取了“同步锁”,之后,线程才转为就绪状态。处于运行的线程synchronized,加上后 变成同步操作。处于锁定状态,获取了“同步锁”,之后,线程才转为就绪状态。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。