线程API应该怎么用
1、setPriority 设置线程的优先级
public final void setPriority(int newPriority)
说明:
setPriority :
- 更改此线程的优先级。 首先调用这个线程的checkAccess方法,没有参数
- 这可能会导致抛出SecurityException 异常。否则该线程的优先级设置为指定的小 newPriority 和最大允许的线程的线程组的优先级。
public static void main(String[] args) {
Thread thread1 = new Thread(new ThreadApi_2(), "t1");
thread1.setPriority(5);
Thread thread2 = new Thread(new ThreadApi_2(), "t2");
thread2.setPriority(10);
thread1.start();
thread2.start();
}
// 定义的另一个类
class ThreadApi_2 implements Runnable {
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("[ 线程名称 ] —> " + thread.getName() + " [ 开始执行] -> " + thread.getState());
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
System.out.println("[ 线程名称 ] —> " + thread.getName() + " [ 线程状态] -> " + thread.getState());
System.out.println("sleep exception cause -> " + e.getMessage());
}
}
}
输出结果:
[ 线程名称 ] —> t2 [ 开始执行] -> RUNNABLE
[ 线程名称 ] —> t1 [ 开始执行] -> RUNNABLE
结论:
你会发现怎么执行都是 thread2 线程先执行因为该线程的优先级最大
2、isDaemon、setDaemon 守护线程API
说明:
isDaemon : 当前线程是否是守护线程
setDaemon :
- 将此线程标记为守护线程或者为用户线程。 当运行的唯一线程都是守护进程线程时,Java虚拟机将退出。
- 线程启动前必须调用此方法,否则会跑出一个IllegalThreadStateException异常
public static void main(String[] args) {
Thread thread = new Thread(new ThreadApi_2());
Thread thread1 = new Thread(new ThreadApi_2());
// 设置当前线程为守护线程
thread.setDaemon(true);
thread.start();
thread1.start();
System.out.println(" 当前线程 -> "+ thread.getName() +" 是否是守护线程 " + thread.isDaemon());
System.out.println(" 当前线程 -> "+ thread1.getName() +" 是否是守护线程 " + thread1.isDaemon());
Scanner scanner = new Scanner(System.in);
scanner.next();
// Registers a new virtual-machine shutdown hook
// 注册一个新的虚拟机关闭钩子
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("java 虚拟机关闭");
}
});
}
// 定义的另一个类
class ThreadApi_2 implements Runnable {
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("[ 线程名称 ] —> " + thread.getName() + " [ 开始执行] -> " + thread.getState());
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
System.out.println("[ 线程名称 ] —> " + thread.getName() + " [ 线程状态] -> " + thread.getState());
System.out.println("sleep exception cause -> " + e.getMessage());
}
}
}
输出结果说明:
当只有一个 thread 线程被设置为守护线程时此时在控制台输入一个信息回车后,java 虚拟机就会被关闭,如下:只是输入aa回车后
输出结果:
当前线程 -> Thread-0 是否是守护线程 true
[ 线程名称 ] —> Thread-0 [ 开始执行] -> RUNNABLE
aa
java 虚拟机关闭
但是又设置了一个 thread1 为用户线程时(非守护线程)此时在控制台输入一个信息回车后,java 会等到非守护线程执行完才会关闭,此时在控制台输入了111 但是并没有立即退出JVM 而是等到了 Thread-1 线程执行完后才退出
输出结果:
当前线程 -> Thread-0 是否是守护线程 true
当前线程 -> Thread-1 是否是守护线程 false
[ 线程名称 ] —> Thread-0 [ 开始执行] -> RUNNABLE
[ 线程名称 ] —> Thread-1 [ 开始执行] -> RUNNABLE
111
java 虚拟机关闭
结论:
- 在守护线程中产生的新线程也是守护线程
- 守护线程不能用于去访问固有资源,比如读写操作因为它会在任何时候甚至在一个操作的中间发生中断
- 存在的意义:当主线程结束时,结束其余的子线程(守护线程)自动关闭。如:Java垃圾回收线程就是一个典型的守护线程
3、线程中断
说明: 上图(网络中断)全是泪啊
interrupt :中断这个线程,如果该线程阻塞的调用wait() , wait(long) ,或wait(long, int)的方法Object类,或者在join() , join(long) , join(long, int) , sleep(long) ,或sleep(long, int) ,这个类的方法,那么它的中断状态将被清除,并且将收到一个InterruptedException
isInterrupted:测试这个线程是否被中, 线程的中断状态不受此方法的影响。
interrupted:测试当前线程是否中断。 该方法可以清除线程的中断状态 。 换句话说,如果这个方法被连续调用两次,那么第二个调用将返回false(除非当前线程再次中断,在第一个调用已经清除其中断状态之后,在第二个调用之前已经检查过)
public static void main(String[] args) {
Thread thread = new Thread(new ThreadApi_2());
thread.start();
thread.interrupt();
System.out.println("thread interrupted status " + thread.isInterrupted());
}
// 定义的另一个类
class ThreadApi_2 implements Runnable {
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("[ 线程名称 ] —> " + thread.getName() + " [ 开始执行] -> " + thread.getState());
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
System.out.println("[ 线程名称 ] —> " + thread.getName() + " [ 线程状态] -> " + thread.getState());
System.out.println("sleep exception cause -> " + e.getMessage());
}
}
}
输出结果:
thread interrupted status true
[ 线程名称 ] —> Thread-0 [ 开始执行] -> RUNNABLE
[ 线程名称 ] —> Thread-0 [ 线程状态] -> RUNNABLE
sleep exception cause -> sleep interrupted
结论:
该代码只是简单的演示了一下线程在 sleep 的状态下简单的调用 interrupt() 中断当前线程与 isInterrupted() 检测当前线程的中断状态,在后续文章中会详细的介绍 (interrupted、interrupt 、isInterrupted)
4、isAlive 、join 、线程状态
说明:
isAlive : 测试这个线程是否活着。 如果一个线程已经启动并且尚未死亡,那么线程是 isAlive 的
join : 等待这个线程死亡,即等待当前线程把手里的活干完
线程状态 : NEW 、 TERMINATED 、RUNNABLE (目前三个) 后续文章中会讲解其他的状态
public static void main(String[] args) {
Thread t1 = new Thread(new ThreadApi_1(), "t1");
Thread t2 = new Thread(new ThreadApi_1(), "t2");
t1.start();
try {
// isAlive 测试这个线程是否活着。 如果一个线程已经启动并且尚未死亡,那么线程是活着的
System.out.println("[线程名称 -> " + t1.getName() + "] [线程状态 -> " + t1.getState() + "] [是否活着 -> " + t1.isAlive() + "]");
System.out.println("[线程名称 -> " + t2.getName() + "] [线程状态 -> " + t2.getState() + "] [是否活着 -> " + t2.isAlive() + "]");
t1.join(); // 等到 t1 线程执行完成此时 t1 线程的状态为 TERMINATED 线程 t2 一直是 NEW 状态 (一直也没启动)
System.out.println("[线程名称 -> " +t1.getName() + " - 执行完成]");
System.out.println("[线程名称 -> " +t1.getName() + "] [线程状态 -> " + t1.getState() + "] [是否活着 -> " + t1.isAlive() + "]");
System.out.println("[线程名称 -> " +t2.getName() + "] [线程状态 -> " + t2.getState() + "] [是否活着 -> " + t2.isAlive() + "]");
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
try {
t2.join(); // 等到 t2 线程执行完成此时 t2 线程的状态为 TERMINATED
System.out.println("[线程名称 -> " +t2.getName() + " - 执行完成]");
System.out.println("[线程名称 -> " +t2.getName() + "] [线程状态 -> " + t2.getState() + "] [是否活着 -> " + t2.isAlive() + "]");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 定义了另一个类
class ThreadApi_1 implements Runnable {
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + " [ 开始执行] -> " + thread.getState());
while (ThreadApi.COUNT <= ThreadApi.MAX_COUNT) {
System.out.println(thread.getName() + " -> " + ThreadApi.COUNT++);
}
}
}
输出结果:
[线程名称 -> t1] [线程状态 -> RUNNABLE] [是否活着 -> true]
[线程名称 -> t2] [线程状态 -> NEW] [是否活着 -> false]
t1 [ 开始执行] -> RUNNABLE
t1 -> 1
t1 -> 2
t1 -> 3
t1 -> 4
t1 -> 5
t1 -> 6
t1 -> 7
t1 -> 8
t1 -> 9
t1 -> 10
t1 -> 11
t1 -> 12
t1 -> 13
t1 -> 14
t1 -> 15
t1 -> 16
t1 -> 17
t1 -> 18
t1 -> 19
t1 -> 20
[线程名称 -> t1 - 执行完成]
[线程名称 -> t1] [线程状态 -> TERMINATED] [是否活着 -> false]
[线程名称 -> t2] [线程状态 -> NEW] [是否活着 -> false]
t2 [ 开始执行] -> RUNNABLE
[线程名称 -> t2 - 执行完成]
[线程名称 -> t2] [线程状态 -> TERMINATED] [是否活着 -> false]
5、activeCount、getName 等简单的API
说明:
getThreadGroup : 返回当前线程的线程组
activeCount : 返回当前线程的thread group及其子组中活动线程数的估计
enumerate : 将当前线程的线程组及其子组中的每个活动线程复制到指定的数组中
getName : 返回此线程的名称
getId : 返回此线程的标识符
getPriority : 返回此线程的优先级
getState : 当前线程的执行状态
new Thread(()->{
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("activeCount -> "+ threadGroup.activeCount());
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (Thread thread : threads) {
System.out.println("Thread name -> " + thread.getName() + ", ID -> "+
thread.getId() + ", Priority -> " + thread.getPriority() + ", state -> " + thread.getState());
}
},"t1").start();
try {
Thread.sleep(5_100);
} catch (InterruptedException e) {
e.printStackTrace();
}
输出结果:
activeCount -> 2
Thread name -> main, ID -> 1, Priority -> 5, state -> TIMED_WAITING
Thread name -> t1, ID -> 13, Priority -> 5, state -> RUNNABLE
关注我,我会一直持续输出… 期待下一期的多线程的学习
与君共勉 …