Thread类方法介绍

文章目录

        • 1. sleep方法
        • 2. join方法
        • 3. start方法
        • 4. run方法
        • 5. name和priority的相关方法
        • 6. daemon相关方法

1. sleep方法

  • Thread.sleep(long millis)
    值不能为负值,否则会抛 IllegalArgumentException 异常
  • Thread.sleep(long millis, int nanos)
    可以传入纳米时长,更精准控制时间,nanos取值范围为(0-999999)
  1. 调用Thread.sleep()方法会使线程调度器把当前线程至于TIMED_WAITING状态,一旦时间结束,线程的状态会变回RUNNABLE并等待CPU执行,因此线程的实际sleep时间会稍大于设定的时间,这取决于操作系统的线程调度器以及系统是否繁忙。
  2. 调用Thread.sleep()方法总是会暂停当前线程的执行。线程sleep时不会丢失线程已经获取到的监视器锁。
  3. 任何其它线程都可以打断当前线程的sleep,在这种情况下会抛出 InterruptedException 异常。

2. join方法

  • threadInstance.join()
    暂停当前线程直到调用join()方法的线程结束,如果该线程被打断,将抛出InterruptedException。
  • threadInstance.join(long millis)
    millis表示最长等待时间,当前线程最多暂停millis毫秒,或者直到调用该方法的线程结束。由于线程执行取决于操作系统的实现,因此不能保证当前线程的等待时长刚好等于指定时长,通常会稍大于该时长。
  • threadInstance.join(long millis, int nanos)
    这个方法是为了能更精准地控制等待时长。

写个例子来测试下:
接受一个名字和时长的Thread类

public class MyThread extends Thread{    
        private String threadName;    
        private long millis = 1000L;        
        
        public MyThread(String name, long millis){
                this.threadName = name;       
                this.millis = millis;    
        }    
        
        @Override    
        public void run() {        
                Printer.print(threadName + " started. start time = " + Timer.getTime());        
                super.run();        
                try {            
                        sleep(millis);       
                }catch (Exception e){            
                        e.printStackTrace();       
                }        
                Printer.print(threadName + " finished. finish time = " + Timer.getTime());    
        }
 }

然后来测试join方法

public static void main(String[] args){    
        MyThread thread1 = new MyThread("Thread 1", 2000);    
        MyThread thread2 = new MyThread("Thread 2", 2000);    
        MyThread thread3 = new MyThread("Thread 3", 2000);    
        
        thread1.start();    
        try {        
                thread1.join();   
        } catch (InterruptedException e){}    
        
        thread2.start();   
        try {        
                thread2.join(1000);    
        } catch (InterruptedException e){}    
        
        thread3.start();   
        
        try {        
                thread1.join();        
                thread2.join();        
                thread3.join();    
        } catch (InterruptedException e){}    
        
        Printer.print("all threads are finished!");
}

根据代码,thread1运行结束之后,thread2开始运行,thread2运行1秒钟之后,thread3开始运行,等三个线程全部运行结束之后,打印出“all threads are finished”。运行程序,输出结果如下:

Thread 1 started. start time = 2019-01-30 10:13:28
Thread 1 finished. finish time = 2019-01-30 10:13:30
Thread 2 started. start time = 2019-01-30 10:13:30
Thread 3 started. start time = 2019-01-30 10:13:31
Thread 2 finished. finish time = 2019-01-30 10:13:32
Thread 3 finished. finish time = 2019-01-30 10:13:33
all threads are finished!

可以看到,输出结果与代码逻辑非常符合。


3. start方法

  • threadInstance.start() : 开始运行该线程

有没有想过,如果对同一个线程调用两次start()方法,会怎么样呢?

Thread thread = new MyThread("testThread", 1000);
thread.start();
thread.start();

运行上面这段代码,会抛出如下异常:

Exception in thread "main" java.lang.IllegalThreadStateException


4. run方法

  • threadInstance.run()
    如果构建Thread实例的时候传入了Runnable对象,此方法将调用Runnable对象的run()方法,否则将什么都不做。

运行如下代码:

Thread thread = new MyThread("testThread", 1000);
thread.run();
Printer.print("print anything");

输出结果:

testThread started. start time = 2019-01-30 11:21:44
testThread finished. finish time = 2019-01-30 11:21:45
print anything

可以看到,直到thread运行结束,打印器才打印了print anything,可见调用run()方法并没有新开一个线程,而是在当前线程运行的。

我们将thread.run()改为thread.start(),运行代码,输出结果如下:

print anything
testThread started. start time = 2019-01-30 11:24:05
testThread finished. finish time = 2019-01-30 11:24:06

这才是是新开了线程运行的输出结果。

可以得出的结论:Thread调用run()方法只会在当前线程执行,调用start()方法才会在新线程中执行。


5. name和priority的相关方法

  • public String getName() : 获取线程的名字
  • public void setName(String name) : 设置(更改)线程的名字
  • public int getPriority() : 获取线程的优先级
  • public void setPriority(int priority) : 设置(更改)线程优先级

6. daemon相关方法

  • public void setDaemon(boolean status)
    设置线程是否为守护(daemon)线程,这个方法必须在线程开始运行之前调用
  • public boolean isDaemon()
    获取线程是否为守护线程

通常执行某个具体任务的线程我们称之为使用线程(user thread),而守护线程(daemon thread)则是用来为使用线程服务的,它们默默无闻地在背后运行,执行一些支持任务,比如垃圾回收。

创建一个线程时,新线程会默认继承当前线程的prioritydaemon状态。

  1. 当所有的使用线程都执行结束之后(或者说当进程中只剩下守护线程),JVM会关闭它自己
  2. 如果JVM在关闭之前发现了守护线程,它会先终结守护线程然后关闭自己。但JVM并不关心守护线程有没有在运行
  3. 守护线程的线程优先级极低

你可能感兴趣的:(Java)