1.线程自身信息
线程运行的过程会产生很多信息,这些信息都保存在Thread类中的成员变量里面,常见的有:
a.线程的ID是唯一标识getId()
b.线程的名称:getName(),如果不设置线程名称默认为“Thread-xx”
c.线程的优先级:getPriority,线程优先级从1-10,其中数字越大表示优先级别越高,同时获得JVM调度执行的可能性越大,JDK内置了三种常见的状态:
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
一般不推荐设置线程的优先级,如果进行设置了非法的优先级程序就会出现IllegalArgumentException异常。
2.线程的几个状态
1.Java线程有六种状态
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
上面六种状态图如下:
2.线程状态的解释
1.当线程继承Thread或者实现了Runnable创建了线程对象后,当new线程对象过后线程就进入了初始的状态。
2.当线程对象调用了start()方法的时候,线程启动进入可运行的状态。
3.线程进入可运行状态后,如果逻辑完成那么线程将会终结,如果没有执行完毕中间JVM分配时间片用完,将进入可运行状态,一旦线程被JVM选中则立即执行。
4.运行状态的情况比较复杂
第一:线程如果执行run() main()方法结束后,完成逻辑,线程就进入Terminated
第二:当线程调用sleep()或者join()方法就会进入Blocked状态,但是要注意的是阻塞的线程是不释放当前所占有的系统资源,当sleep()结束或者join()等待其他线程来到,当前线程则进入Runnable状态等待JVM分配资源。
第三:当线程进入Runnable状态,但是还没有开始运行的时候,此时发现需要的资源处于同步状态synchronized,这个时候线程将会进入Time waiting,JVM会使用队列对这些线程进行控制,既先进行Time waiting的线程会先得到JVM资源进行执行进入Waiting
第四:如果处于Runnable的线程调用yield()让出JVM资源,那么就会进入New状态和其他New状态线程进行竞争重新进入Runnable
第五:如果当前线程调用wait()方法,则当前线程进入Time waiting但是这个时候当前线程会释放所占有的JVM资源,进入这个状态过后是不能自动唤醒的,必须调用notify()或者notifyAll()方法,线程进入Waiting。
3.案例解释
案例:用案例解释线程的六种运行状态,其中Pig类实现Runnable接口,逻辑是打印当前运行的线程信息,
每隔一秒打印一次。在Main方法中启动十个Pig线程设置相应的线程优先级别,并且将初始的线程状态
保存到线程状态数组中,在运行的过程判断当前线程状态和初始状态是否相同,如果不同则打印当前线
程的信息保存到日志文件中。
class Pig implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadName : " + Thread.currentThread().getName());
}
}
}
public class App {
public static void main(String[] args) throws Exception {
Thread[] taskArr = new Thread[10];
Thread.State[] threadStates = new Thread.State[10];
for (int i = 0; i < 10; i++) {
taskArr[i] = new Thread(new Pig());
if ((i % 3) == 0) {
taskArr[i].setPriority(Thread.NORM_PRIORITY);
} else if ((i % 3) == 1) {
taskArr[i].setPriority(Thread.MIN_PRIORITY);
} else if ((i % 3) == 2) {
taskArr[i].setPriority(Thread.MAX_PRIORITY);
}
}
FileWriter fWriter = new FileWriter(".\log.txt");
PrintWriter pWriter = new PrintWriter(fWriter);
for (int i = 0; i < 10; i++) {
pWriter.println("线程 " + i + " 状态:" + taskArr[i].getState());
threadStates[i] = taskArr[i].getState();
}
for (int i = 0; i < 10; i++) {
taskArr[i].start();
}
boolean finish = false;
while (!finish) {
for (int i = 0; i < 10; i++) {
if (taskArr[i].getState() != threadStates[i]) {
printThreadMsg(pWriter, taskArr[i], threadStates[i]);
threadStates[i] = taskArr[i].getState();
}
}
finish = true;
for (int i = 0; i < 10; i++) {
finish = finish && (taskArr[i].getState() == State.TERMINATED);
}
}
}
/** * 打印当前线程的信息 * @param pWriter * @param thread * @param state */
private static void printThreadMsg(PrintWriter pWriter, Thread thread, State state) {
pWriter.println("*********************************************************");
pWriter.println("线程ID: " + thread.getId() + " 线程名称:" + thread.getName());
pWriter.println("线程优先级:" + thread.getPriority());
pWriter.println("线程过去状态:" + state);
pWriter.println("线程当前状态:" + thread.getState());
pWriter.println("*********************************************************");
}
}
部分执行结果如下:
分析上面的部分执行结果就可以看出当Pig线程进行休眠的时候,就会导致其他线程状态的变换,其中过去状态和当前状态可以明显的反应出线程状态切换。