4.4.多线程&JUC-多线程中的常用成员方法
细节:这个细节不止是currentThread方法的细节,而是整个Java虚拟机的细节, 当JVM虚拟机启动之后,会自动启动多条线程,其中有一条线程就叫做main线程,main线程的作用就是去调用main方法,并执行main方法里的代码,在以前,我们写的所有代码,其实都是运行在main线程当中的。注:currentThread方法的作用是获取当前线程的对象,也就是说哪条线程执行到这个current
一.常见的成员方法:

- 第三个sleep方法的形参就是指定休眠时间,单位为毫秒,比如传递参数1000,就是休眠1s
- Java中线程的优先级最小是1,最大是10,默认是5,优先级越大,抢占到CPU的概率越高
二.方法演示:
1.getName方法:
代码:
package com.itheima.a04threadmethod;
public class ThreadDemo {
public static void main(String[] args) {
/*演示getName方法:如果没有给线程设置名字,那线程有默认的名字吗?答案是有*/
//1.创建线程的对象
MyThread t1=new MyThread();
MyThread t2=new MyThread();
//2.开启线程
t1.start();
t2.start();
}
}
package com.itheima.a04threadmethod;
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + "@" + i);
//此时@前的就是线程的名字
}
}
}
运行结果如下:

如上图,
运行结果中@前是有数据的,该数据就是线程默认的名字,
本例中是Thread-0和Thread-1,格式是Thread加-,再加一个序号,序号从0开始,
getName方法的细节:
Ⅰ.如果没有给线程设置名字,线程也是有默认的名字的->格式:Thread-X(X是序号,从0开始的),源码如下:

如上图,是Thread类里的一个空参构造,用this关键字调用了其他的构造,在第三个参数中就是给线程设置名字,前面的Thread-就是固定格式,后面加了一个方法nextThreadNum,nextThreadNum源码如下:

nextThreadNum方法的作用就是变量threadInitNumber不断的自增,然后返回threadInitNumber的值,threadInitNumber一开始默认为0,所以第一个线程默认的序号为0,
注:threadInitNumber++是先参与运行,再自增,所以第一次调用nextThreadNum方法时,里面的threadInitNumber为0并返回,然后自增为1,第二次调用nextThreadNum方法时threadInitNumber为1并返回,然后自增为2。
2.setName方法:
代码:
package com.itheima.a04threadmethod;
public class ThreadDemo {
public static void main(String[] args) {
/*演示getName方法:如果没有给线程设置名字,那线程有默认的名字吗?答案是有*/
//1.创建线程的对象
MyThread t1=new MyThread();
MyThread t2=new MyThread();
/*给线程设置名字*/
t1.setName("线程1");
t2.setName("线程2");
//2.开启线程
t1.start();
t2.start();
}
}
package com.itheima.a04threadmethod;
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + "@" + i);
//此时@前的就是线程的名字
}
}
}
运行结果:

如上图,可以得知两个线程是交替运行的。
3.Thread类的构造方法也是可以给线程命名的:
该构造方法详情如下:

形参是String型,变量名为name,该形参就是给线程设置的名字,
还有一个构造方法是两个形参,如下图:

第一个参数是Runnable接口,所以第一个形参可以传递线程的任务对象,
第二个参数String name就是线程名字。
实例:


如上图,在MyThread的构造方法里命名后,系统报错了,
这是因为现在创建的是MyThread对象,MyThread类虽然是Thread类的子类,但此时只有Thread类里有可以给线程命名的构造方法,由于构造方法不能继承,所以MyThread类里就没有能给线程命名的构造方法,
因此如果子类MyThread想要用父类Thread的构造方法给线程命名该怎么办呢?只需要在子类MyThread里写一个利用super关键字去调用父类的构造方法的方法即可,正确代码如下:
package com.itheima.a04threadmethod;
public class ThreadDemo {
public static void main(String[] args) {
/*演示getName方法:如果没有给线程设置名字,那线程有默认的名字吗?答案是有*/
//1.创建线程的对象
MyThread t1=new MyThread("飞机");
MyThread t2=new MyThread("坦克");
//2.开启线程
t1.start();
t2.start();
}
}
package com.itheima.a04threadmethod;
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
/*super(name)就是访问父类的构造方法*/
/*该MyThread方法的形参name的值会通过super(name)传递给其父类Thread的构造方法,
而且传给的是父类中只有一个形参且形参类型为String的构造方法Thread,该构造方法Thread也正是给线程命名的构造方法*/
super(name);
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + "@" + i);
//此时@前的就是线程的名字
}
}
}
运行结果:

总结:如果要给线程设置名字,可以用setName方法,也可以用构造方法Thread。
3.currentThread方法(静态方法):该方法是空权限修饰符,意味着别的软件包里的类无法直接使用,可以类名.方法名进行调用
演示currentThread方法,现在不开启线程,
直接调用currentThread方法,这时获取到的线程对象是什么呢?
注:currentThread方法的作用是获取当前线程的对象,也就是说哪条线程执行到这个currentThread方法,此时获取到的就是哪条线程的对象->
细节:这个细节不止是currentThread方法的细节,而是整个Java虚拟机的细节, 当JVM虚拟机启动之后,会自动启动多条线程,其中有一条线程就叫做main线程,main线程的作用就是去调用main方法,并执行main方法里的代码,在以前,我们写的所有代码,其实都是运行在main线程当中的。
package com.itheima.a04threadmethod;
public class ThreadDemo {
public static void main(String[] args) {
/*演示currentThread方法,现在不开启线程,
* 直接调用currentThread方法,这时获取到的线程对象是什么呢?
* 注:currentThread方法的作用是获取当前线程的对象,也就是说
* 哪条线程执行到这个currentThread方法,此时获取到的就是哪条线程的对象*/
Thread t = Thread.currentThread();
//此时这个变量t,就表示执行main方法的线程对象
String name = t.getName();
System.out.println(name); //打印结果为main
/*打印结果为main,这是什么意思呢?
* 细节:这个细节不止是currentThread方法的细节,而是整个Java虚拟机的细节,
* 当JVM虚拟机启动之后,会自动启动多条线程,
* 其中有一条线程就叫做main线程,
* main线程的作用就是去调用main方法,并执行main方法里的代码,
* 在以前,我们写的所有代码,其实都是运行在main线程当中的*/
}
}
4.sleep方法(静态方法):该方法是空权限修饰符,意味着别的软件包里的类无法直接使用,可以类名.方法名进行调用
细节:
- 哪条线程执行到这个sleep方法,那么哪条线程就会在这里停留对应的时间
- 停留的时间与sleep方法的参数有关->sleep方法的参数:就表示睡眠(停留)的时间,单位是毫秒(例如:1秒=1000毫秒)
- 当睡眠(停留)时间结束之后,线程会自动的醒来,继续执行下面的其他代码
例一:
package com.itheima.a04threadmethod;
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
/*细节:
* 1.哪条线程执行到这个sleep方法,那么哪条线程就会在这里停留对应的时间;
* 2.停留的时间与sleep方法的参数有关->sleep方法的参数:就表示睡眠(停留)的时间,单位是毫秒
* 1秒=1000毫秒
* 3.当睡眠(停留)时间结束之后,线程会自动的醒来,继续执行下面的其他代码*/
//让main方法进行休眠
System.out.println("111111");
Thread.sleep(5000); //让main方法睡眠5s
System.out.println("222222222"); //睡眠后再执行该语句
/*运行结果中先运行了输出111111,隔了5s后才输出222222222,
* 为什么会有这种效果呢?其实就是因为main线程被sleep方法停留了5s,
* 时间到了之后就会继续执行下面的代码*/
}
}
例二:
package com.itheima.a04threadmethod;
public class ThreadDemo {
public static void main(String[] args) {
/*细节:
* 1.哪条线程执行到这个sleep方法,那么哪条线程就会在这里停留对应的时间;
* 2.停留的时间与sleep方法的参数有关->sleep方法的参数:就表示睡眠(停留)的时间,单位是毫秒
* 1秒=1000毫秒
* 3.当睡眠(停留)时间结束之后,线程会自动的醒来,继续执行下面的其他代码*/
//1.创建线程的对象
MyThread t1=new MyThread("飞机");
MyThread t2=new MyThread("坦克");
//2.开启线程
t1.start();
t2.start();
/*最终的运行就是每隔1s打印1次*/
}
}
package com.itheima.a04threadmethod;
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
/*super(name)就是访问父类的构造方法*/
/*该MyThread方法的形参name的值会通过super(name)传递给其父类Thread的构造方法,
而且传给的是父类中只有一个形参且形参类型为String的构造方法Thread,该构造方法Thread也正是给线程命名的构造方法*/
super(name);
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000); //停留1000毫秒即1s
/*此时就不能抛出异常了,只能try,因为父类Thread里的run方法是没有抛出异常的,
* 父类的run方法没有抛出异常,那么其子类里的run方法就不能抛出异常,子类只能自己try*/
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName() + "@" + i);
//此时@前的就是线程的名字
}
}
}
更多推荐


所有评论(0)