目录
Thread类是我们在线程学习过程中常见的使用,我们要想熟悉运用可以从一下几个方面来学习,线程创建、线程中断、线程等待、线程休眠、获取线程实例。
1. 线程创建
线程的创建我们,可以通过
- 继承 Thread, 重写 run
- 实现 Runnable, 重写 run
- 继承 Thread, 重写 run, 使用匿名内部类
- 实现 Runnable, 重写 run, 使用匿名内部类
- 使用 lambda 表达式
这五种方式来实现。
1.1 继承Thread
public class 继承Thread {
public static void main(String[] args) {
// 继承的方法一:
// 创建一个线程
myThread myThread = new myThread();
myThread.start();
// 继承的方法二:
// 使用一个匿名内部类
Thread t = new Thread() {
@Override
public void run() {
System.out.println("匿名内部类 run");
}
};
}
// 继承的方式,1.继承Thread。2.重写run方法
private static class myThread extends Thread {
@Override
public void run() {
System.out.println("MyThread run");
}
}
}
1.2 实现Runnable
public class 实现Runnable {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
Runnable r = new Runnable() {// 属于runnable接口实现类,只是没有名字
@Override
public void run() {
System.out.println("匿名内部类 run");
}
};
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
}
});
t2.start();
}
private static class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("MyRunnable run");
}
}
}
1.3 使用lambda表达式
Thread t3 = new Thread(() -> System.out.println("匿名内部类 run"));
t3.start();
2. 线程中断
上面创建的线程,启动它的命令就是我们看到的.start();命令,但是这个命令一但启动,那就必须执行完才可以结束,但是实际运用中我们不可能只进行这一个线程,如果想要进行其他的线程,我们就要接触到这一节的内容。
目前常见的有以下两种方式:
- 通过共享的标记来进行
- 调用 interrupt() 方法
2.1 自定义标记位
public class 自定义标记为 {
//先设计一个标志位:表示是否被中断。这里volatile后续学习
private static volatile boolean 是否被中断 = false;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
//循环10次,每次打印次数,并休眠1秒
try {
//判断条件加上标志位
for (int i = 0; i < 10 && !是否被中断; i++) {
System.out.println(i);
//自定义标志位,能够实现某些条件的中断
//但如果线程处于等待/超时等待/阻塞, 就没法中断
//修改时间为100秒就没法中断
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
//要中断t线程:等3后再中断
Thread.sleep(3000);
是否被中断 = true;
}
}
2.2 调用 interrupt() 方法
我们先来认识一下interrupt()方法:
方法 | 说明 |
public void interrupt() | 中断对象关联的线程,如果线程正在阻塞,则以异常方式通知, 否则设置标志位 |
public static boolean interrupted() | 判断当前线程的中断标志位是否设置,调用后清除标志位 |
public boolean isInterrupted() | 判断对象关联的线程的标志位是否设置,调用后不清除标志位 |
public class ThreadDemo {
private static class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.interrupted());
}
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable target = new MyRunnable();
Thread thread = new Thread(target, "李四");
thread.start();
thread.interrupt();
}
}z
//结果
true // 只有一开始是 true,后边都是 false,因为标志位被清
false
false
false
false
false
false
false
false
false
--使用 Thread.currentThread().isInterrupted() , 线程中断标记位不会清除
public class ThreadDemo {
private static class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().isInterrupted());
}
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable target = new MyRunnable();
Thread thread = new Thread(target, "李四");
thread.start();
thread.interrupt();
}
}
// 结果
true // 全部是 true,因为标志位没有被清
true
true
true
true
true
true
true
true
true
3. 线程等待
线程的等待就是在执行一个线程的时候,等待一个线程完成它的工作后,才能进行自己的下一步工作。
这是我们就要使用join()方法;
方法 | 说明 |
public void join() | 等待线程结束 |
public void join(long millis) | 等待线程结束,最多等 millis 毫秒 |
public void join(long millis, int nanos) | 同理,但可以更高精度 |
public class Demo {
public static void main(String[] args) throws InterruptedException {
Runnable target = () -> {
for (int i = 0; i < 10; i++) {
try {
System.out.println(Thread.currentThread().getName()
+ ": 我还在工作!");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ": 我结束了!");
};
Thread thread1 = new Thread(target, "李四");
Thread thread2 = new Thread(target, "王五");
System.out.println("先让李四开始工作");
thread1.start();
thread1.join();
System.out.println("李四工作结束了,让王五开始工作");
thread2.start();
thread2.join();
System.out.println("王五工作结束了");
}
}
4. 线程休眠
方法 | 说明 |
public static void sleep(long millis) throws InterruptedException | 休眠当前线程 millis 毫 秒 |
public static void sleep(long millis, int nanos) throws InterruptedException | 可以更高精度的休眠 |
public class Demo {
public static void main(String[] args) throws InterruptedException {
System.out.println(System.currentTimeMillis());
Thread.sleep(3 * 1000);
System.out.println(System.currentTimeMillis());
}
}
注意休眠和等待的区别;
5. 获取线程实例
这个经过前面的学习我们应该已经很熟悉了。
方法 | 说明 |
public static Thread currentThread(); | 返回当前线程对象的引用 |
public class Demo {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
}
}