Java 多线程(一)Thread

线程的六种状态

1.新建状态

new了但是没有启动的线程的状态,如“Thread thread = new Thread()”,thread就是一个处于新建状态的线程。

2.运行状态

new出来的线程,调用strat()方法即处于入运行状态(Runnable),处于运行状态的线程可能正在Java虚拟机中运行,可能正在等待处理器的资源,因为一个线程必须获得CPU的资源后,才可运行其run()方法中的内容,否则排队等待。

3.阻塞状态

如果某个线程正在等待监视器锁,以便进入同步方法或同步方法块,那么这个线程就是阻塞状态的。

4.等待状态

某一线程因为调用不带超时Object的wait()方法,不带超时的Thread的join()方法,LockSupport的park()方法,就会处于等待状态。

5.超时等待状态

某一线程因为调用带有指定等待时间的Object的wait()方法,Thread的join()方法,Thread的sleep()方法,LockSupport的parkNanos()方法,LockSupport的parkUntil()方法,就会处于超时等待状态。

6.终止状态

线程调用终止或run()方法执行结束后,就会进入终止状态,处于终止状态的线程不具备继续运行的能力。

Thread实例的方法

start()方法

启动线程,等待CPU调用线程对象的run()方法,产生一个异步执行的效果。

注意: 多个线程同时调用start()方法时,CPU启动线程的顺序是随机的。调用start()方法的顺序不代表启动顺序。线程的启动具有随机性

run()方法

线程开始执行,虚拟机调用run()方法里面的内容

注意: 如果只调用run()方法,不调用start()方法启动线程,将全部由main函数执行,没有异步效果。只调用run()方法没有任何意义

isAlive()方法

测试线程是否处于活动状态,只要线程启动且没有终止,就会返回true

getId()方法

在一个Java应用中,有一个long型的全局唯一的线程ID生成器threadSeqNumber,每new出来一个线程,这个生成器都自增一次,并赋予线程的tId属性,这个是Thread自己做的,用户无法执行一个线程的Id

getName()方法

在new一个线程时,可以指定该线程的名字,通过getName()方法即可获得该线程的名字。如果不指定名字,Thread中有一个int型的全局唯一的线程初始号生成器threadInitNum,Java先把threadInitNum自增,然后以“Thread-threadInitNum”来命名新生成的线程

getPriority()方法和setPriority(int newPriority)方法

这两个方法用于获取和设置线程的优先级,优先级高的线程越容易先被执行,设置优先级有助于帮助“线程规划器”确定下一次选择哪个线程优先执行。两个在等待CPU的线程,优先级高的线程越容易被CPU执行

补充: 线程的默认优先级为5,如果不手动指定,线程的优先级具有继承性,比如线程main启动线程A,那么A的优先级和main的优先级相同。CPU会尽量将执行资源让给优先级高的线程

isDaemon()方法和setDaemon(boolean on)方法

判断该线程是否为守护线程,或将该线程设为守护线程(true)

Java中有两种线程,一种是守护线程,一种是用户线程。守护线程是一种特殊的线程,它的作用是为其他线程的运行提供便利的服务,最典型的应用便是GC线程。如果线程中只有守护线程了,那么守护线程会自动销毁。

注意: setDaemon()方法必须在start()方法之前

interrupt()方法

在线程受到阻塞时,抛出一个中断信号,使线程退出阻塞状态,没有被阻塞的线程,调用interrupt()方法没有作用

join()方法

join()方法的作用是等待线程销毁,join()方法会使得调用该方法的线程(如线程A.join()即A)所在的线程(如果在main方法中运行即main)无限阻塞,直到调用join()方法的线程销毁为止,main线程会无限阻塞直到线程A的run()方法执行完毕。

join(long millis)方法表示等待该线程销毁的时间最长为mills毫秒,该方法与sleep()方法的区别为:

sleep(2000)方法不释放锁,join(2000)方法释放锁。join()方法内部使用wait()方法,因此会释放锁。join()就是join(0)

public final void join() throws InterruptedException {
        join(0);
    }

 

join(long mills)的源码:

 1 public final synchronized void join(long millis)
 2     throws InterruptedException {
 3         long base = System.currentTimeMillis();
 4         long now = 0;
 5 
 6         if (millis < 0) {
 7             throw new IllegalArgumentException("timeout value is negative");
 8         }
 9 
10         if (millis == 0) {
11             while (isAlive()) {
12                 wait(0);
13             }
14         } else {
15             while (isAlive()) {
16                 long delay = millis - now;
17                 if (delay <= 0) {
18                     break;
19                 }
20                 wait(delay);
21                 now = System.currentTimeMillis() - base;
22             }
23         }
24     }

 

Thread的静态方法

Thread类的静态方法表示操作的线程是“正在执行静态方法所在的代码块的线程”。Thread使用静态方法,就能对CPU当前正在运行的线程进行操作

currentThread()方法

currentThread()方法返回的是对当前正在执行线程的对象引用

注意: 线程类的构造方法,静态代码块是由main线程调用的,而线程类的run()方法是由应用线程自己调用(前提是启动了线程start()方法)

补充: this.XXX()方法和Thread.currentThread.XXX()方法中的对象不一定是相同的。换句话说就是当前执行的Thread未必就是Thread本身,比如执行线程的构造方法的是main线程,而不是该线程。

sleep(long millis)方法

让当前正在执行的线程休眠millis毫秒,这个“当前正在执行的线程”指的是Thread.currentThread()方法返回的线程。根据JDK API的说法:“该线程不丢失任何监视器的所属权”,简单说就是sleep代码上下文如果被加锁了,锁依然在,但CPU资源会让给其他线程。

yield()方法

暂停当前执行的线程对象,并执行其他线程。这个暂停会放弃CPU的资源,并且放弃CPU的资源不确定,有可能刚放弃就获得了资源,也有可能放弃好一会,CPU才执行

 interrupted()方法

测试当前线程是否已经中断,执行后具有将状态标识清除为false的功能(线程的中断状态 由该方法清除),换句话说如果两次调用该方法,返回的必定是false

posted @ 2018-03-01 19:54  羽觞醉月  阅读(308)  评论(0编辑  收藏  举报