线程睡眠唤醒问题,一直不明白,请给解释一下.程序来自:Java 案例大全

nmyangym 2011-11-05 03:35:43
/* 1 getUp()里的这句, Thread.currentThread().interrupt(); 要把谁唤醒? 这个线程是谁?
2 text.join(),这句要一直执行完,执行完后,这个线程结束了. 但怎么输出的结果"Thread-0 15-26-45:0570Thread-0 唤醒异常:sleep interrupted" 还有Thread-0呢?
*/


package com.zf.s14; //创建一个包
import java.text.DateFormat; //引入类
import java.text.SimpleDateFormat;
import java.util.Date;
public class TextSleepAndInterrupt extends Thread { // 操作线程沉睡与唤醒的类
private DateFormat dateFormat = new SimpleDateFormat("HH-mm-ss:SSSS");
public void run() {
System.out
.println(dateFormat.format(new Date()) + getName() + " 沉睡3秒钟");
try {
sleep(3000); // 线程休眠3秒
} catch (InterruptedException e) { // 捕获唤醒异常
System.out.println(getName() + dateFormat.format(new Date())
+ getName() + " 唤醒异常:" + e.getMessage());
}
System.out.print(dateFormat.format(new Date()) + " 沉睡期间是否唤醒?");
try {
sleep(2000); // 线程休眠2秒
} catch (InterruptedException e) { // 捕获唤醒异常
System.out.println(getName() + dateFormat.format(new Date())
+ getName() + " 唤醒异常:" + e.getMessage());
}
System.out.println(!isAlive()); // 线程是否激活,false表示不是激活的
interrupt();// 唤醒线程
System.out.print(dateFormat.format(new Date()) + " 沉睡的我,是否唤醒?");
System.out.println(isAlive()); // 线程是否激活
}
public void getUp(){
Thread.currentThread().interrupt(); // 唤醒当前线程
while (true) {
if (Thread.currentThread().isInterrupted()) { // 判断当前线程是否被唤醒
System.out.println(dateFormat.format(new Date())+" 当前我是否被唤醒 ?"
+ Thread.currentThread().isInterrupted());
try {
Thread.currentThread().sleep(2000); // 线程休眠2秒
} catch (InterruptedException e) { // 捕获唤醒异常
System.out.println(getName() + dateFormat.format(new Date())
+ getName() + " 唤醒异常:" + e.getMessage());
}
System.out.println(dateFormat.format(new Date())+" 沉睡后是否被唤醒?"
+ Thread.currentThread().isInterrupted());
}
}
}
public static void main(String[] args) { // java程序主入口处
TextSleepAndInterrupt text=new TextSleepAndInterrupt();//实例化对象
text.start(); //启动线程
try {
text.join(); //等待线程运行结束
} catch (InterruptedException e) { // 捕获唤醒异常
System.out.println(" 唤醒异常:" + e.getMessage());
}
text.getUp(); //调用方法判断是否唤醒
}
}
/* 这是运行输出结果

5-26-40:0569Thread-0 沉睡3秒钟
15-26-43:0570 沉睡期间是否唤醒?false
15-26-45:0570 沉睡的我,是否唤醒?true
15-26-45:0570 当前我是否被唤醒 ?true
Thread-015-26-45:0570Thread-0 唤醒异常:sleep interrupted
15-26-45:0570 沉睡后是否被唤醒?false
*/

...全文
686 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
shaosijun2004 2011-11-07
  • 打赏
  • 举报
回复
LZ,这个不是唤醒,这个是线程中断,线程在sleep的时候是阻塞等待的,如果收到中断信号,就会在调用的方法(这里是sleep)上抛出InterruptedException异常,这个是中断线程。。

唤醒是 wait 和 notify 、 notifyAll,在线程wait在某的管程上时,可以有线程对此管程上的线程做notify或 notifyAll 操作,来唤醒wait在此管程上的线程
shaosijun2004 2011-11-07
  • 打赏
  • 举报
回复
这个时候还没有调用过当前线程的interrupt方法所以 ,线程未被 中断,所以isAlive()返回true
!isAlive()返回false


这里写错了,因为线程还没执行完毕,所以isAlive()是返回true
shaosijun2004 2011-11-07
  • 打赏
  • 举报
回复
TextSleepAndInterrupt text=new TextSleepAndInterrupt();//实例化对象
text.start(); //启动线程

System.out.println(dateFormat.format(new Date()) + getName() + " 沉睡3秒钟");
sleep(3000);
System.out.print(dateFormat.format(new Date()) + " 沉睡期间是否唤醒?");
sleep(2000);
System.out.println(!isAlive()); // 线程是否激活,false表示不是激活的
这个时候还没有调用过当前线程的interrupt方法所以 ,线程未被 中断,所以isAlive()返回true
!isAlive()返回false

即打印
5-26-40:0569Thread-0 沉睡3秒钟
15-26-43:0570 沉睡期间是否唤醒?false

接下来你调用了
interrupt();
这个时候 当前线程收到中断信号,但线程还未结束所以isAlive()返回true
打印出
15-26-45:0570 沉睡的我,是否唤醒?true
现在TextSleepAndInterrupt线程执行完毕

text.join();//这句的意思就是等text线程执行完毕 再继续执行当前线程

TextSleepAndInterrupt线程执行完毕后,执行

text.getUp();
其实这个调用是main线程在调用的
进入方法后
Thread.currentThread().interrupt(); // 唤醒当前线程
则main线程接收到中断信号
if (Thread.currentThread().isInterrupted()) 返回true
进入if

执行
System.out.println(dateFormat.format(new Date())+" 当前我是否被唤醒 ?"
+ Thread.currentThread().isInterrupted());
此时线程已接收到中断信号,即Thread.currentThread().isInterrupted()为true

所以显示
15-26-45:0570 当前我是否被唤醒 ?true

接下来执行
try {
Thread.currentThread().sleep(2000); // 线程休眠2秒
} catch (InterruptedException e) { // 捕获唤醒异常
System.out.println(getName() + dateFormat.format(new Date())
+ getName() + " 唤醒异常:" + e.getMessage());
}

因为main 线程已经 收到过中断信号 (就是进入方法的时候调用 的Thread.currentThread().interrupt(); ),所以调用方法的时候直接就抛出了InterruptedException,
所以执行System.out.println(getName() + dateFormat.format(new Date())
+ getName() + " 唤醒异常:" + e.getMessage());
打印了出
Thread-015-26-45:0570Thread-0 唤醒异常:sleep interrupted

最后的
System.out.println(dateFormat.format(new Date())+" 沉睡后是否被唤醒?"
+ Thread.currentThread().isInterrupted());


因为main的中断信号已经 被 处理(即抛出了InterruptedException),所以main线程恢复到未被 中断状态,所以Thread.currentThread().isInterrupted()返回false
打印出
15-26-45:0570 沉睡后是否被唤醒?false
nmyangym 2011-11-07
  • 打赏
  • 举报
回复
在text.start(),起动后到,到text.join(),之前,应是 两个线程。 我也觉得到text.join()结束后是一个线程了。 问题就在这,在运行text.getUp()后,getName()输出 “thread-0",而Thread.currenThread().getName(),输出main. 不明白为什么?



24K純帥 2011-11-07
  • 打赏
  • 举报
回复
LZ你不就只有一个线程么
饭饭吃 2011-11-07
  • 打赏
  • 举报
回复
不是都说线程问题都在每个线程里建个print来看就可以了么.。喵.
  • 打赏
  • 举报
回复
学习中
nmyangym 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 shaosijun2004 的回复:]
LZ,这个不是唤醒,这个是线程中断,线程在sleep的时候是阻塞等待的,如果收到中断信号,就会在调用的方法(这里是sleep)上抛出InterruptedException异常,这个是中断线程。。

唤醒是 wait 和 notify 、 notifyAll,在线程wait在某的管程上时,可以有线程对此管程上的线程做notify或 notifyAll 操作,来唤醒wait在此管程上的线程
[/Quote]

4楼讲得,我这几天一直在思考,明白了一些.
现在不明白我在3楼那发的那个结果.

(那些注释都是原程序上注的,暂不去管. ).现在的问题:
1 join 结束后,text.start(),启动的线程是否结束? run 方法结束了.
2 text.getUp(),调用了线程类对象的非run()方法,这时是否需要起动线程? 这也是我在3楼问的问题。
为什么 getName(),得到的是 "thread-0"? 这个"thread-0" 是text.start()启动后的线程名,在
join(),运行结束后,这个线程不存在了,怎么会得到这个名字? (我想应该是main). 用
Thread.current().getName()得到的是main. 这个我怎么也理解不了。
nmyangym 2011-11-07
  • 打赏
  • 举报
回复
我现在明白了,谢谢各位!

所有的 getName(),等于this.getName(),是得到当前对象的线程名字。与其启动不启动无关。只要你新建(new)一个线程的对象,JVM 就给一个线程编号。
而Thread.currentThread().getName(),是当前正在运行的现成名字。

例子中的这句:
System.out.println(getName() + dateFormat.format(new Date())
+ getName() + " 唤醒异常:" + e.getMessage());
用 getName()似乎不妥,因为这时thread-0 线程名存在,(线程也应存在),但是非启动的线程,对这样的线程来说,不存在唤醒什么问题。

我刚试着在getUp()方法的try/catch块里,加上interrupt()语句,和Thread.currentThread().interrupt()语句。结果是不一样的:interrupt()语句,加上这个语句,对程序运行没有任何作用了,而Thread.currentThread().interrupt();则会起作用,会使try/catch块d语句重复运行!

非常感谢各位!
shaosijun2004 2011-11-07
  • 打赏
  • 举报
回复
你要看清楚,getName返回是线程TextSleepAndInterrupt 的名字,这个是实例方法,返回的是本线程的名字,只是说我已经执行完了,但我的名字还是我的,如果你想打出main,那应该告诉他我要打出的名字是执行你的这个线程的名字
Thread.currentThread.getName();

给你个例子,你研究下

public class StubTest {
public static void main(String[] args) throws Exception{
Rund r = new Rund();
r.start();
r.join();
r.d();
}

static class Rund extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub

}
public void d(){
System.out.println(getName());
System.out.println(Thread.currentThread().getName());
}
}
}
cyl713 2011-11-07
  • 打赏
  • 举报
回复
首先要理解一个概念,线程一旦wait()。自己是不可能唤醒自己的!要其他线程来唤醒它
当线程Await()时候,让出CPU,多线程的情况下,会跳到其他线程执行
nmyangym 2011-11-07
  • 打赏
  • 举报
回复
因为main 线程已经 收到过中断信号 (就是进入方法的时候调用 的Thread.currentThread().interrupt(); ),所以调用方法的时候直接就抛出了InterruptedException,
所以执行System.out.println(getName() + dateFormat.format(new Date())
+ getName() + " 唤醒异常:" + e.getMessage());
打印了出
Thread-015-26-45:0570Thread-0 唤醒异常:sleep interrupted

感谢10楼写得很详细,现在是上面这段,为什么getName()输出不是main,而是thread-0?
我试过输出,Thread.currentThread().getName(),输出的是main.
而 getName()就输出thread-0, 现在就困惑在这里了!
(按说thread-0 在join()结束后,线程结束了啊!)
nmyangym 2011-11-06
  • 打赏
  • 举报
回复
程序执行到 " text.getUp();" 应该是text.join(),执行结束了,或说text线程已经结束了. 是不是这样?

而在text.getUp()里面, Thread.currentThread().getName() 得到的是main 线程, 而getName()得到的是Thread-0, 这怎么解释?
nmyangym 2011-11-05
  • 打赏
  • 举报
回复
请问1楼,当前线程是 main? Thread-0?
qichao88888 2011-11-05
  • 打赏
  • 举报
回复
Thread.currentThread().interrupt();是将当前线程中断,让出CPU.

62,615

社区成员

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

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