多线程每一次运行都是不同的运行结果,因为它会根据自己的情况进行资源抢占(除非加锁)。要区分每一个线程,那么必须依靠线程的名字。对于线程名字,一般而言会在其启动之前进行定义,不建议对已经启动的线程更改名称/设置不同线程重名。
如过要想进行线程名称的操作,可以使用Thread类如下方法。
1.构造方法:
public Thread(Runnable target,String name)
2.普通方法(并且无法被子类覆写)
public final void setName(String name)
与之对应的getName()取得名字。
对于线程名字操作会出现一个问题,这些方法属于Thread类,Runnable接口子类(MyThread类)无法取得线程名字,能取得的只有当前正在执行的线程名。
Thread类中有一个currentThread的静态方法可供调用,结果这个问题
public static Thread currentThread();
范例:观察线程的命名:
package TestDemo;
class MyThread implements Runnable{//Runnable接口子类,也是线程公有对象,其实例化对象在堆中
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class TestDemo{
public static void main(String[] args)throws Exception{
MyThread mt=new MyThread();
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();
}
}
image.png
如果在实例化Thread类对象的时候没有为其设置名字,会自动命名,用以保证线程对象名字不重复。
范例:使用构造方法命名:
package TestDemo;
class MyThread implements Runnable{//Runnable接口子类,也是线程公有对象,其实例化对象在堆中
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class TestDemo{
public static void main(String[] args)throws Exception{
MyThread mt=new MyThread();
new Thread(mt,"Thread A").start();
new Thread(mt).start();
new Thread(mt,"Thread B").start();
new Thread(mt).start();
new Thread(mt).start();
}
}
结果:
image.png
上面讲完了,我们来点拓展:
package TestDemo;
class MyThread implements Runnable{//Runnable接口子类,也是线程公有对象,其实例化对象在堆中
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class TestDemo{
public static void main(String[] args)throws Exception{
MyThread mt=new MyThread();
new Thread(mt,"Thread A").start();
mt.run();
}
}
image.png
主方法就是一个线程(main线程 主线程)所有在main方法里创建的线程都可以视作子线程(new Thread()构造生成),这在Android开发中很常见,因为要开辟子线程进行一些耗时操作如网络请求等)
通过以上代码可以发现,线程实际上一直都存在(主方法就是主线程),可是进程去哪里了呢,其实每次使用java命令去解释一个程序类/使用IDE编译源代码时候,对于操作系统而言都想与开辟了一个新进程,而main线程只是新进程中的一个子线程而已。
提问:每一个JVM进程启动的时候至少启动几个线程?
main线程:程序的主要执行,以及启动子线程
gc线程:负责垃圾收集
网友评论