Thread.sleep()的用法:
package com.thread;
/**
* @Description:
*/
public class SleepDemo implements Runnable{
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
System.out.println("当前线程:"+Thread.currentThread().getName()+"休眠1秒");
Thread.currentThread().sleep(1000);
System.out.println("当前线程:"+Thread.currentThread().getName()+"休眠1秒");
} catch (InterruptedException e) {
System.out.println("当前线程:"+Thread.currentThread().getName()+"休眠时被中断");
System.out.println("当前中断状态为:"+Thread.currentThread().isInterrupted());
break;
}
}
}
public static void main(String[] args) throws InterruptedException {
SleepDemo sleepDemo=new SleepDemo();
Thread t1=new Thread(sleepDemo);
t1.setName("sleepDemo");
t1.start();
System.out.println("当前线程:"+Thread.currentThread().getName());
t1.sleep(50);
System.out.println("注意:t1.sleep仍然是main线程进入休眠了");
Thread.sleep(2000);
t1.interrupt();
}
}
运行结果:
当前线程:main 注意:t1.sleep仍然是main线程进入休眠了 当前线程:sleepDemo休眠1秒 当前线程:sleepDemo休眠1秒 当前线程:sleepDemo休眠时被中断 当前中断状态为:false
总结:
Thread.sleep(1000); 与 Thread.currentThread().sleep(1000); 等价,都是在何处调用,就会使得当前的线程进入休眠状态。因此,t1.sleep(50); 同样是main线程休眠了50毫秒。
sleep()支持中断,因此当检测到中断信号时,会抛出InterruptedException 异常,从而告知程序该线程应当对中断进行某些响应操作。通过isInterrupted()可以发现:在抛出异常的时候,还让异常状态重新置为了false。
需要注意:由于不允许不同的线程之间的异常溢出,因此在run方法中就必须对此处抛出的InterruptedException异常进行处理,因此上述示例代码,直接对异常进行了捕捉。若是在其他的普通方法中,除非是线程需要退出,否则都不应当直接将异常生吞。此时可以选择:1.不捕捉 InterruptedException,将它传播给调用者;2.捕捉InterruptedException执行必要的清理操作,重新向上抛出InterruptedException异常;3.捕捉 InterruptedException 后重新恢复中断状态。
sleep方法不会释放锁。如果当前线程持有对某个对象的锁,则即使调用了sleep方法,其他线程也无法获得这个对象的锁。
Thread.currentThread()的用法:
Thread.currentThread()返回对当前正在执行的线程对象的引用。换句话说, Thread.currentThread() 返回的是一个实例。这个实例是当前Thread 的引用。
Thread.start()的用法:
源码:
public synchronized void start() {
// 线程不能重复start,否则会抛出IllegalThreadStateException
if (threadStatus != 0)
throw new IllegalThreadStateException();
//添加到线程组,启动数加1,启动失败数减1
group.add(this);
boolean started = false;
try {
start0();//启动线程的native方法
started = true;//启动成功
} finally {
try {
if (!started) {//若启动失败
group.threadStartFailed(this);//从线程组移除,启动失败数加1
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
一个线程启动另一个线程执行的唯一方法。
Thread.run()的用法:
源码:
@Override //实现了Runnable的run方法
public void run() {
if (target != null) {
target.run();
}
}
target为Runnable成员变量实例,可以发现若直接执行run方法,并没有执行启动另一个线程的相关操作,因此执行的仍然是执行run方法的那个线程而已,等同于执行了另一个实例对象中方法名为run的普通方法。
需要注意:target对象的初始化时在Thread的构造方法中完成的。
Thread的构造函数:
public Thread() {//无参构造器
init(null, null, "Thread-" + nextThreadNum(), 0);//初始化线程名称为'Thread-'加当前线程数,线程栈大小为0
}
//Runnable target 实现了Runnable接口的类的实例
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);//初始化线程名称为'Thread-'加当前线程数,线程栈大小为0
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
//ThreadGroup group 当前建立的线程所属的线程组.如果不指定线程组,所有的线程都被加到一个默认的线程组中
//Runnable target 实现了Runnable接口的类的实例
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);//初始化线程名称为'Thread-'加当前线程数,线程栈大小为0
}
//String name 线程的名字
public Thread(String name) {
init(null, null, name, 0);//初始化线程栈大小为0
}
//ThreadGroup group 当前建立的线程所属的线程组.如果不指定线程组,所有的线程都被加到一个默认的线程组中
//String name 线程的名字
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);//初始化线程栈大小为0
}
//Runnable target 实现了Runnable接口的类的实例
//String name 线程的名字
public Thread(Runnable target, String name) {
init(null, target, name, 0);//初始化线程栈大小为0
}
//ThreadGroup group 当前建立的线程所属的线程组.如果不指定线程组,所有的线程都被加到一个默认的线程组中
//Runnable target 实现了Runnable接口的类的实例
//String name 线程的名字
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);//初始化线程栈大小为0
}
//ThreadGroup group 当前建立的线程所属的线程组.如果不指定线程组,所有的线程都被加到一个默认的线程组中
//Runnable target 实现了Runnable接口的类的实例
//String name 线程的名字
//long stackSize 线程栈的大小
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
Thread.stop()的用法:强制线程停止执行。(不推荐使用!)
Thread.yield()的用法:
Thread.interrupt()的用法:
interrupted()
isInterrupted()
Thread.setName()方法:设置线程的名字。
public final synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}
注意:在调用start方法前后都可以使用setName设置线程名,但在调用start方法后使用setName修改线程名,会产生不确定性,也就是说可能在run方法执行完后才会执行setName。如果在run方法中要使用线程名,就会出现虽然调用了setName方法,但线程名却未修改的现象。