文章目录


​上一篇文章:Thread开启线程​

Thread中常用的方法

  • ​void run()​​//不推荐使用
  • ​void start()​​​//开启线程,该方法会开启新的线程,并调用​​void run()​​方法
  • ​void setName(String name)​​//设置线程的名称,通常用于调试
  • ​String getName()​​//获取线程的名称
  • ​long getId()​​//获取线程 id,该 id 是由系统分配的,每个线程的 id 是唯一的

栗子1:setName()

CustomThread

class CustomThread extends Thread {
public CustomThread() {
setName("自定义线程类");
}

@Override
public void run() {
super.run();
for (int i = 0; i < 10; i++) {
System.out.println(getName() + i);
}
}
}

Main

public class Main {
public static void main(String[] args) {
System.out.println("主线程开始-----------------");

CustomThread thread = new CustomThread();
thread.start();

for (int i = 0; i < 10; i++) {
System.out.println("Main i=" + i);
}

System.out.println("主线程结束");
}
}

运行结果

主线程开始-----------------
Main i=0
......
Main i=9
主线程结束
自定义线程类0
......
自定义线程类9

栗子2:getId()

name 可以重复,id 是不会重复的

代码改为

CustomThread

System.out.println(getName() + "(" + getId() + ")" + i);

运行结果:

主线程开始-----------------
Main i=0
......
Main i=9
主线程结束
自定义线程类(13)0
......
自定义线程类(13)9

栗子3:currentThread()

刚才的一些操作都是在自定义的线程类中操作的,如果想在在主线程中获取 id,或者在 Runnable 接口中获取id,就需要依靠以下方法

  • ​static Thread currentThread()​​//获取当前线程的对象

Main

System.out.println("主线程开始");

CustomThread thread = new CustomThread();
thread.start();

for (int i = 0; i < 10; i++) {
System.out.println("Main(" + Thread.currentThread().getId() + ") i=" + i);
}

System.out.println("主线程结束");

输出结果(主线程的id是1)

主线程开始
Main(1) i=0
......
Main(1) i=8
Main(1) i=9
主线程结束
自定义线程类(13)0
自定义线程类(13)1
......
自定义线程类(13)7
自定义线程类(13)8
自定义线程类(13)9

Process finished with exit code 0

同样的 CustomRunner 可以改为

CustomRunner

class CustomRunner implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("CustomRunner(" + Thread.currentThread().getId() + ")i=" + i);
}
}
}

栗子4:sleep(long timeMillis)

  • ​void sleep(long timeMillis)​​//休眠,使得线程在接下来的 timeMillis 时间不工作

Main 代码修改为

long start = System.currentTimeMillis();

for (int i = 0; i < 60; i++) {
System.out.println(new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

long end = System.currentTimeMillis();

System.out.println(end - start);

运行结果是:程序每秒执行一次,输出当前时间
【达内课程】Thread相关方法_i++
再写一个关于 sleep 的栗子

Main 代码改为

System.out.println("主线程开始");
//子线程1
CustomThread ct = new CustomThread();
ct.start();

//子线程2
CustomRunner cr = new CustomRunner();
Thread t = new Thread(cr);
t.start();

try {
t.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

//主线程
for (int i = 0; i < 100; i++) {
System.out.println("Main i=" + i);
}

System.out.println("主线程结束");

运行程序:

主线程开始
CustomRunner(14)i=0
CustomRunner(14)i=1
......
CustomRunner(14)i=9
自定义线程类(13)0
......
自定义线程类(13)9
Main i=0
Main i=1
......
Main i=99
主线程结束

子线程1和子线程2交替执行,5秒钟后,主线程执行

其实代码中的 ​​t.sleep(5000);​​​ 可以写成 ​​ct.sleep(5000);​​​ 或者 ​​Thread.sleep(5000);​

sleep 这句代码出现在哪个线程中,表示的就是哪个线程 sleep,刚才的代码中,sleep 出现在 main() 中,所以主线程休眠 5s 执行了。

如果想让子 线程2 休眠,应该在 CustomRunner 中加

class CustomRunner implements Runnable {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
System.out.println("CustomRunner(" + Thread.currentThread().getId() + ")i=" + i);
}
}
}

执行结果:子线程 1 和主线程交替执行,5秒后,子线程 2 执行

最后说一个细节

反复创建对象,很耗费内存,在刚才栗子4中的代码中,for 循环中创建了60个 Date 对象,可以优化为

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Date d = new Date();

for (int i = 0; i < 60; i++) {
d.setTime(System.currentTimeMillis());
System.out.println(sdf.format(d));

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

或者

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Date d = new Date();
long timeMillis = d.getTime();

for (int i = 0; i < 60; i++) {
d.setTime(timeMillis);
System.out.println(sdf.format(d));

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

timeMillis += 1000;
}
}