1、守护线程 t.setDaemon(true)
守护线程相对于正常线程来说,是比较特殊的一类线程,守护线程是服务提供者线程。
Java官方文档:
The Java Virtual Machine exits when the only threads running are all daemon threads.
当 JVM 中不存在任何一个正在运行的非守护线程时,则 JVM 进程即会退出。
- **①:**创建一个非守护线程;
- **②:**模拟非守护线程不退出的情况;
- **③:**启动线程;
- **④:**主线程即将退出;
从下面的例子进行理解:
public class NoDaemonTeat {
public static void main(String[] args) {
Thread t = new Thread(NoDaemonTeat::print);
t.setDaemon(false);
t.start();
System.out.println("Exiting main method");
}
public static void print() {
int counter = 1;
while (true) {
try {
System.out.println("Counter:" + counter++);
Thread.sleep(2000); // sleep for 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出:
Counter:1
Exiting main method
Counter:2
Counter:3
Counter:4
Counter:5
Counter:6
…………
从输出结果看,主线退出,而非守护线程不退出,正因为有一个非守护线程一直在后台运行着,JVM 无法正常退出。
现在我们试一试开启守护线程,并设计一个钩子线程,用于监听JVM:
public class NoDaemonTeat {
public static void main(String[] args) {
//设计一个钩子线程,用于监听JVM
Runtime.getRuntime().addShutdownHook(new Thread(()->System.out.println("The JVM is exited")));
Thread t = new Thread(NoDaemonTeat::print);
t.setDaemon(true);
t.start();
System.out.println("Exiting main method");
}
public static void print() {
int counter = 1;
while (true) {
try {
System.out.println("Counter:" + counter++);
Thread.sleep(2000); // sleep for 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出结果:
Counter:1
Exiting main method
The JVM is exited
这时主线程退出,JVM也同时退出了。
以上可知:守护线程拥有自动结束自己生命周期的特性,而非守护线程不具备这个特点。
应用:通常来说,守护线程经常被用来执行一些后台任务,但是呢,你又希望在程序退出时,或者说 JVM 退出时,线程能够自动关闭,此时,守护线程是你的首选。
例如:JVM 中的垃圾回收线程就是典型的守护线程。
2、礼让线程 t.yield()
礼让不一定成功,看CPU心情
//测试礼让线程
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程结束");
}
}
结果:
a线程开始
b线程开始
a线程结束
b线程结束
3、线程睡眠 t.sleep()
很好理解,就是线程延时。
import java.text.SimpleDateFormat;
import java.util.Date;
//获取并更新系统时间
public class TestSleep {
public static void main(String[] args) {
Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间
while (true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
startTime = new Date(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
4、线程加入 t.join
在JDk的API里对于join()方法是:
join
public final void *join()* throws InterruptedException Waits for this thread to die. Throws: InterruptedException - if any thread has interrupted the current thread. The *interrupted status* of the current thread is cleared when this exception is thrown.
public final void join() throws InterruptedException等待线程死亡。抛出:InterruptedException——如果有线程中断了当前线程。当抛出这个异常时,当前线程的“中断状态”将被清除。
简单的说,就是在子线程调用join后,主线程应等待子线程完成,才继续进行。
用途:子线程需要大量运算的时候。
public class TestJoin implements Runnable{
@Override
public void run() {
System.out.println("线程VIP" );
}
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin =new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
for (int i=0;i<100;i++){
if (i==20){
thread.join();
}
System.out.println("main"+i);
}
}
}
输出结果:
main0
……
main19
线程VIP
main20
…………
main99
5、线程优先级
在Java程序设计语言中,每一个线程有一个优先级。默认情况下,一个线程会继承构造它的那个线程的优先级。可以用 setPriority方法提高或降低任何一个线程的优先级。可以将优先级设置为MIN PAIORITY (在Thread 类中定义为1)与 MX PRIORLITY (定义为10)之间的任何每当线程调度器有机会选择新线程时,它首先选择具有较高优先级的线程。但是,线程优先级高度依赖于系统。当虚拟机依赖于宿主机平台的线程实现时,Java线程的优先级会映射到宿主机平台的优先级,平台的线程优先级别可能比上述的10个级别多,也可能更少。
例如,Windows有7个优先级别。Java的一些优先级会映射到同一个操作系统优先级。
在Oracle为Linux提供的Java虚拟机中,会完全忽略线程优先级——所有线程都有相同的优
在没有使用操作系统线程的Java早期版本中,线程优先级可能很有用。不过现在不要使用优先级了。
void setPriority(int newPriority)
设置线程的优先级。优先级必须在Thread.MIN_PRIORITY与Thread.MAX PRIORITY之间。一般使用Thread.NORM_PRIORITY优先级。
是Thread可以有的最小优先级。最小优先级的值为1。
Thread 的默认优先级。默认优先级为5。
是Thread可以有的最大优先级。最大优先级的值为10。