获取线程信息
Thread提供了获取线程信息的相关方法:
long getId():返回该线程的标识符
String getName():返回该线程的名称
int getPriority();返回线程的优先级
Thread.state getState():获取线程的状态
boolean isAlive():测试线程是否处于活动状态
boolean isDaemon():测试线程是否为守护线程
boolean isInterrupted();测试线程是否已经中断
Thread main = Thread.currentThread();
// 获取线程名字
System.out.println(main.getName()); // main
// 获取线程的唯一标识
long id = main.getId();
System.out.println(id); // 1
int priority = main.getPriority();
System.out.println(priority); // 5
boolean isAlive = main.isAlive();
System.out.println(isAlive); // true
// 获取该线程是否为守护线程
boolean isDaemon = main.isDaemon(); // false
System.out.println(isDaemon);
// 线程是否被中断
boolean isInterrupted = main.isInterrupted();
System.out.println(isInterrupted); // false
线程优先级
线程的切换是由线程调度控制的,我们无法通过代码来干涉,但是我们通过提高线程的优先级来最大程度的改善线程获取时间片的几率。
线程的优先级被划分为10级,值分别为1-10,其中1最低,10最高。线程提供了3个常量来表示最低,最高,以及默认优先级:
Thread.MIN_PRIORITY
Thread.MAX_PRIORITY
Thread.NORM_PRIORITY
void setPriority(int priority):设置线程的优先级。
守护线程
守护线程与普通线程在表现上没有什么区别,我们只需要通过Thread提供的方法来设定即可:
void setDaemon(boolean)
当参数为true时该线程为守护线程。
守护线程的特点是,当进程中只剩下守护线程时,所有守护线程强制终止。
GC就是运行在一个守护线程上的。
public class Daemon1 {
public static void main(String[] args) {
Thread rose=new Thread() {
public void run() {
for(int i=0;i<5;i++) {
System.out.println("rose:let me go!");
try {
Thread.sleep(1000);
}catch(InterruptedException e) {
}
}
System.out.println("rose:啊啊啊啊啊AAAaaaaaa");
System.out.println("噗通!");
}
};
Thread jack=new Thread() {
public void run() {
while(true) {
try {
System.out.println("you jump I jump");
Thread.sleep(1000);
}catch(InterruptedException e) {
}
}
}
};
//设置为守护线程,需要注意,设置守护线程必须在线程start方法调用之前进行
jack.setDaemon(true);
rose.start();
jack.start();
while(true) {
}
}
}
//守护线程里的finally代码块不一定执行
public class DaemonsDontRunFinally {
public static void main(String[] args) {
Thread t=new Thread(new Adaemon());
t.setDaemon(true);
t.start();
System.out.println(1);
}
}
class Adaemon implements Runnable{
public void run() {
try {
System.out.println("Starting ADaemon");
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e) {
System.out.println("Exiting via InterruptedException");
} finally{
System.out.println("This shounld always run?");
}
}
}
Sleep方法
Thread的静态方法sleep用于使当前线程进入阻塞状态:
--static void sleep(long ms)
该方法会使当前线程进入阻塞状态指定毫秒,当阻塞指定毫秒后,当前线程会重写进入Runnable状态,等待分配时间片。
该方法声明抛出一个InterruptException。所以在使用该方法需要捕获这个异常。
public class SleepD {
public static void main(String[] args) {
while (true) {
System.out.println("你好!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
yield方法
Thread的静态方法yield:
-static void yield()
该方法用于使当前线程主动让片出当次CPU时间片回到Runnable状态,等待分配时间片.
Join方法
Thread的方法join:
-void join()该方法用于等待当前线程结束。
该方法声明抛出InterruptException
public class JoinDemo {
// 标示图片下载完毕的状态
public static boolean isFinish;
public static void main(String[] args) {final Thread download = new Thread() {
public void run() {
System.out.println("down:开始下载图片..");
for (int i = 1; i <= 100; i++) {
System.out.println("down:" + i + "%");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
System.out.println("down:图片下载完毕!");
isFinish = true;
}
};
download.start();
Thread show=new Thread() {
public void run() {
System.out.println("show:开始显示图片");
//先在这里等待download将图片下载完毕
try {
/*
* 在jdk8之前,由于JVM内存分配问题,导致有一个使用要求,即当一个方法的局部内部类中想引用这个方法的其他。
* 局部变量时,这个变量必须是final的。
* 例如下面的例子
* main方法的局部变量dow
*
*
* nload想在main方法的局部内部类show中使用,那么download就必须是final的。
*/
download.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!isFinish) {
throw new RuntimeException("图片加载失败!");
}
System.out.println("show:显示图片成功");
}
};
show.start();
}
}