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方法,但线程名却未修改的现象。

11-10 08:59