线程本身属性不可见的运行状态,即每次操作的时间是无法预料的,所以如果要想在程序中操作线程,唯一的依靠就是线程名称,而想要取得和设置线程的名称可以使用以下方法。
线程的命名和取得
由于多线程的状态不确定,线程的名字就成为唯一的分辨标识,所以在定义线程名称时一定要在线程启动前设置名字,而且尽量不要重名,尽量不要为已经启动的线程修改名字。
由于线程的状态不确定,所以每次可以操作的都是正在执行run()方法的线程实例,依靠Thread类的以下方法实现。
取得当前线程对象:public staticThread currentThread()
范例:观察线程的命名操作
public class MyTread313 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class JavaThread313 {
public static void main(String[] args) {
MyTread313 mt=new MyTread313();
new Thread(mt,"线程A").start(); //设置了线程的名字
new Thread(mt).start(); //未设置线程名称
new Thread(mt,"线程B").start(); //设置线程名称
}
}
执行结果
线程A
Thread-0
线程B
如果已经为线程设置名字的话,那么会使用用户定义的名字;而如果没有设置线程的名称,系统会为其自动分配一个名称,名称的形式以“Thread-xxx”的方式出现。
所有的线程都是在程序启动后在主方法中进行启动的,所以主方法本身也属于一个线程,而这样的线程就称为主线程,通过代码来观察主线程的存在。
范例:观察以下程序代码
public class MyTread313 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class JavaThread314 {
public static void main(String[] args) {
MyTread313 mt=new MyTread313(); //线程类对象
new Thread(mt,"线程A").start(); //设置了线程名字
mt.run(); //对象直接调用run()方法
}
}
执行结果
main(主线程,mt.run()执行结果)
线程A(子线程)
本程序在主方法中直接利用线程实例化对象调用了run()方法,这样所取到的对象就是main线程对象
进程在哪里?
每一个JVM运行就是进程。当用户使用java命令执行一个类的时候就表示启动了一个JVM的进程,而主方法就是这个进程上的一个线程而已,而当一个类执行完毕之后,此进程就会消失。
所有的子线程都是通过主线程来创建的,这样的处理机制主要是可以利用多线程来实现一些资源耗费较多的复杂业务。当程序中存在多线程机制后,就可以将一些耗费时间和资源较多的操作交由子线程处理,这样就不会因为执行速度而影响主线程的执行。
范例:子线程处理复杂逻辑
public class JavaThread314B {
public static void main(String[] args) {
System.out.println("1,执行操作任务1"); //主线程执行
new Thread(()->{ //子线程负责统计
int temp=0;
for (int i = 0; i < Integer.MIN_VALUE; i++) {
temp=+i; //模拟执行耗时操作
}
}).start();
System.out.println("2,执行操作任务1"); //主线程执行
System.out.println("N,执行操作任务N"); //主线程执行
}
}
执行结果
1,执行操作任务1
2,执行操作任务1
N,执行操作任务N
本程序启动了一个子线程进行耗时的业务处理操作,在子线程的执行过程中,主线程的其他代码将不会受到该耗时任务的影响。
如何等待子线程完成?
需要引入线程等待与唤醒机制