Java线程操作相关方法

Java线程操作相关方法

从前面的操作中,我们可以看到无论是实现类 Runable 接口还是继承了 Thread 类,还是实现了 Callable 接口,最终都要通过 Thread 的 start() 方法。所以对线程的操作还是在 Thread 的类中,其主要方法有:

方法名称 描述
public static Thread currentThread() 返回目前正在执行的线程
public final String getName() 返回线程的名称
public final int getPriority() 返回线程的优先级
public boolean isInterrupted() 返回目前的线程是否被中断,如果是,返回 true,否则返回 false。
public final boolean isAlive() 判断线程是否在活动,如果是返回true,如果不是返回false。
public final void setName(String name) 给当前线程设定名称
public void run() 运行当前线程
public static void sleep(long millis) throws InterruptedException 使当前正在执行的线程休眠 millis 毫秒
public void start() 开始执行线程
public static void yield() 将目前正在执行的线程请求暂停,允许其他的同等优先级的线程获得运行机会
public final void join() throws Interrupted Exception 把指定的线程加入当前线程,可以让两个交替的线程顺序执行
public final void setDaemon(boolean on) 将一个线程设置成后台运行

方法详解

获取和设置线程名称

在上面的表格里面我们可以看到获取线程的名称可以用 getName() ,通过 setName() 方法给线程设置名称。线程的名称一般在启动线程之前设置,也允许为已经于心的线程设置名称。允许多个线程拥有相同的名称。但是在真实使用场景中,我们应该避免这样的事情发生。

package com.haicoder.net.thread; public class ThreadName implements Runnable{ @Override public void run() { System.out.println("当前线程名称为:" + Thread.currentThread().getName()); //获取当前线程名称 } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); ThreadName threadName = new ThreadName(); Thread runThread = new Thread(threadName); runThread.setName("线程直接设置名称"); //设置线程名称 runThread.start(); Thread runThread2 = new Thread(threadName,"构造函数设置线程名称"); //构造函数设置线程名称 runThread2.start(); } }

运行效果图如下:

07 线程名称设置和获取.png

从上面运行效果可以看出,在设置线程名称的时候,可以用构造方法,也可以直接为当前线程设置名称,给线程设置名称的好处是在真实的生产场景中,可以方便的定位到是什么样的线程做什么样的事情,方便定位问题。

判断线程是否启动

通过前面的讲解我们知道 Thread 的 start() 方法是通知 CPU 这个线程已经准备好启动了,就等 CPU 来调度了,在线程中判断当前的线程是否存活的函数 isAlive() 方法来测试。

package com.haicoder.net.thread; public class ThreadAlive implements Runnable { @Override public void run() { System.out.println("当前运行着的线程名称为:" + Thread.currentThread().getName()); } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); Thread currentThread = new Thread(new ThreadAlive(),"判断存活状态线程"); //使用构造方法设置线程名称 System.out.println("线程调度前存活状态 : " + currentThread.isAlive()); currentThread.start(); System.out.println("线程调度后存活状态:" + currentThread.isAlive()); } }

运行效果如下:

08 判断线程是否存活.png

从运行结果图中我们可以看到,在调用线程的 start() 方法之前判断线程的状态时,不是存活的,而调用了 start() 方法之后就变成了存活的状态。

线程强制运行

在线程的执行过程中,我们可以使用 join() 方法来让一个线程强制插队,强制执行,这个线程在执行过程中其他的线程无法执行,必须等该线程执行完才能执行。

package com.haicoder.net.thread; public class JoinThread implements Runnable{ @Override public void run() { System.out.println("当前执行的线程名称为 :" + Thread.currentThread().getName()); } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); Thread thread1 = new Thread(new JoinThread(),"Thread - 01"); thread1.start(); Thread thread2 = new Thread(new JoinThread(),"Thread - 02"); thread2.start(); try { thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Main 线程运行 " + Thread.currentThread().getName() ); } }

09 线程join.png

从上面运行效果中我们可以看到最后的 main 线程始终最后执行打印, thread2 线程调用 join() 方法,会将 main 线程挂起,等 Thread - 02 执行结束之后才会执行 main 线程方法。

线程休眠

线程在执行过程中,如果先要进行短暂的阻塞,等自己执行完之后再执行后面的流程,就可以用线程的 sleep() 方法。线程的休眠是不释放 cpu 资源的,即它不释放,其他的线程是不能够获取到被当前线程占用的 cpu 的调度。

package com.haicoder.net.thread; public class SleepThread implements Runnable { @Override public void run() { System.out.println("调用前的时间点:" + System.currentTimeMillis()); try { System.out.println("注意咯,我要睡觉咯!"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("调用后点时间点:" + System.currentTimeMillis()); } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); Thread sleepThread = new Thread(new SleepThread(),"Sleep-Thread"); sleepThread.start(); } }

运行结果如下:

10 线程休眠.png

在线程执行过程中,我们在 run 方法里面调用了 sleep 方法,让该线程休息了 2 秒,在 sleep 的方法中后面的打印输出需要等待差不多 2 秒钟的时间。在真实使用场景中,如果我们后面的一个线程需要前一个线程的执行结果,不考虑性能的情况下,可以考虑使用 sleep 方法来处理。

中断线程

当运行一个线程当时候,如果想终止状态,或者不继续运行,该怎么做呢?我们可以调用线程的 interrupt() 方法来终止线程。

package com.haicoder.net.thread; public class InterruptThread implements Runnable { @Override public void run() { System.out.println("1 进入 run 方法"); try { Thread.sleep(10000); System.out.println("2 已经休眠结束"); } catch (Exception e) { System.out.println("3 休眠被终止"); return; } System.out.println("4 run 方法正常结束"); } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); InterruptThread myThread = new InterruptThread(); Thread thread01 = new Thread(myThread,"Thread 01"); thread01.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { } thread01.interrupt(); } }

运行效果如下:

11 线程终止.png

在 catch 方法体里面,我们直接 return ,线程执行结束了。

后台线程

后台线程是指即使当前 java 的进程结束了,还有一个后台线程会继续执行。比如我们了解到 java 垃圾收集器就是一个后台线程。设置后台线程的方法是 setDaemon() 方法。

package com.haicoder.net.thread; public class DaemonThread implements Runnable { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + "在运行"); } } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); Thread thread01 = new Thread(new DaemonThread()); thread01.setDaemon(true); thread01.start(); } }

运行效果如下图:

12 后台线程.png

我们写了一个死循环,但是当前的操作还是执行完了,我们将调用死循环的线程设置为后台线程。

线程优先级

线程的生命周期 中我们了解到所有的线程在执行之前都是就绪状态,如果这个时候有多个线程在就绪状态,那么哪个线程会优先执行呢?线程这边有优先级的概念,哪个线程的优先级高,就会执行哪个线程。(一般情况下会这样)。在 java 中可以使用 setPriority() 方法进行优先级设置。

定义 描述 表示的常量
MIN_PRIORITY 最低优先级 1
NORM_PRIORITY 中等优先级,线程的默认优先级 5
MAX_PRIORITY 最高优先级 10
package com.haicoder.net.thread; public class PriorityThread implements Runnable { @Override public void run() { for (int i=0;i<3;i++){ try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 运行 " + i); } } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); Thread thread01 = new Thread(new PriorityThread(),"Thread 01"); Thread thread02 = new Thread(new PriorityThread(),"Thread 02"); Thread thread03 = new Thread(new PriorityThread(),"Thread 03"); thread01.setPriority(Thread.MIN_PRIORITY); thread02.setPriority(Thread.NORM_PRIORITY); thread03.setPriority(Thread.MAX_PRIORITY); thread01.start(); thread02.start(); thread03.start(); } }

13 线程优先级.png

从程序的运行结果中可以观察到,线程将根据其优先级的大小来决定哪个线程会先运行,但是并不是哪个线程的优先级越高就一定会先执行,哪个线程的执行还是靠 CPU 来决定。

线程礼让

在线程执行过程中,我们可以使用 yield() 方法让当前线程先暂停,让其他线程执行,等其他线程执行完再执行当前线程。

package com.haicoder.net.thread; public class YieldThread implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { if(i == 3){ System.out.print(Thread.currentThread().getName() + " 线程礼让: " ); Thread.currentThread().yield(); } System.out.println(Thread.currentThread().getName() + " 运行 : " + i); } } public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); YieldThread yieldThread = new YieldThread(); Thread thread01 = new Thread(yieldThread,"Thread 01"); Thread thread02 = new Thread(yieldThread,"Thread 02"); thread01.start(); thread02.start(); } }

14 线程礼让.png

从上面运行效果可以看到,每当线程满足条件 i == 3 的时候,就会将本线程暂停,让其他的线程先执行。