观前提示:本篇博客演示使用的 IDEA 版本为2021.3.3版本,使用的是Java8(又名jdk1.8)
1.线程创建
1.1 继承Thread 重写 run
class MyThreadDemo1 extends Thread {
@Override
public void run() {
while (true) {
System.out.println("Hello Thread");
try {
// 加入sleep,是为了让他打印慢一点,便于观察
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MyThread1 {
public static void main(String[] args) {
Thread t = new Thread();
t.start();
while (true) {
System.out.println("Hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
首先创建一个类,由这个类去继承Thread类,重写其中的run方法
run方法: 创建出来的线程去执行的内容
start方法: 创建出一个新的线程,并让其去执行run方法里面的内容
sleep方法: sleep方法是Thread类中的一个静态方法,它可以让线程进入短暂休息的状态,比如sleep(1000) 就是休息1秒.(注意:sleep方法需要处理异常)
执行上面的代码,可能会出现以下几种情况
1.出现 Hello Thread 和 Hello 交替打印的情况(又分为两种,第一个是 Hello Thread 先打印,第二个是Hello 先打印)
2.只打印 Hello Thread
3.只打印 Hello
这是因为执行完 t.start 之后会创建出来一个线程(暂且叫他 t 线程) t 线程和 main 线程同属于在同一个进程上,他们在操作系统上可能是并发,可能是并行,所以打印的顺序是无法预知的.
1.2 实现 Runnable, 重写 run
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("Hello Runnable");
}
}
public class MyThread2 {
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
Thread t= new Thread(runnable);
t.start();
}
}
首先创建一个类,实现 Runnable 接口,重写里面的run方法.
将 Runnable 对象传到 Thread 的构造方法中,然后 t.start() 线程就创建好了.
1.3 继承 Thread, 重写 run,使用匿名内部类
public class MyThread3 {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run() {
System.out.println("Hello Thread");
}
};
t.start();
}
}
使用了匿名内部类
1.4 实现 Runnable.重写 run,使用匿名内部类
public class MyThread4 {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run() {
System.out.println("Hello Thread");
}
};
t.start();
}
}
将类实现替换成内部类实现
1.5 使用lanbda 表达式
public class MyThread5 {
public static void main(String[] args) {
Thread t = new Thread(()->{
System.out.println("Hello Thread");
});
t.start();
}
}
大括号里面的内容就相当于重写run方法的内容
2.线程中断
中断的意思是:不是让线程立刻停止,而是告诉线程,你该停止了,是否真的停止,取决于线程这里具体的代码写法
第一种:使用标志位来控制线程是否要终止
private static boolean flag = true;
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (flag) {
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = false;
}
我们设置了一个 boolean 类型的静态成员变量,用来实现对 t 线程的控制,实现中断效果
第二种:使用Thread自带的标志位来控制线程是否停止
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (!Thread.currentThread().isInterrupted()){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(3000);
t.interrupt();
}
//Thread.currentThread().
//这是Thread类的静态方法,通过这个方法可以获取到当前线程
//那个线程调用这个方法,就得到那个线程对象的引用
//这个静态方法在 run 中被调用,获取的就是 t 线程
//isInterrupted()
//为 true 表示被终止
//为 false 表示未被终止
//t.interrupt()
//代表可以终止线程
//isInterrupted() 相当于一个 boolean 变量
//t.interrupt() 就是控制变量的
//interrupt会做两件事
//1.把线程内的标志位 (boolean) 设置成 true
//2.如果线程在进行 sleep 就会触发异常,把 sleep 唤醒
//但是, sleep 唤醒的时候,还会顺手把刚才设置的标志位再设置回 false (清空标志位)
此代码运行调用了 Thread 自带的标志位来控制线程是否停止,运行代码我们会发现,他虽然抛出了一个异常,但是代码依然会继续往下运行,这就是前面所说的:"中断的意思是:不是让线程立刻停止,而是告诉线程,你该停止了,是否真的停止,取决于线程这里具体的代码写法"
下面在放一个实现了中断的代码写法
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
//加上这段代码,代码会真的中断
try {
//0.5s后中断
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
break;
}
}
});
t.start();
Thread.sleep(3000);
t.interrupt();
}
3.线程等待
线程是随机调度的过程
等待线程做的事情,就是在控制两个线程的结束顺序
public static void main(String[] args) {
Thread t = new Thread(()->{
for (int i = 0; i < 3; i++) {
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
System.out.println("join 之前" );
// 此处的 join 就是让当前的 main 线程来等待 t 线程执行结束(等 run 结束)
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("join 之后");
}
//t.start() 执行完以后, t 线程和 main 线程,并发执行,分头行动
//t 线程和 main 线程都往下执行, t 遇到 join, 发生阻塞(block)
//此时 main 线程就会阻塞等待,一直等待 t 线程的 run 执行完
//main 线程才会从 join 恢复过来
打印效果就是上面说的, 先打印 "join 之前", t 遇到 join 之后, main 线程开始阻塞等待, 然后 t 线程的 run 开始执行,打印 "hello thread",打印三遍,run 执行完,main 继续往下执行,打印"join 之后"
4.线程休眠
顾名思义:就是让线程休眠一下
public static void main(String[] args) {
Thread t = new Thread(()->{
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
代码效果就是隔1s打印一条"hello thread"
5.获取线程实例
Thread.currentThread()方法
它是一个类方法,作用是获取当前线程的实例
也就是说: 你在哪个线程中去调用这个方法,那么它就会返回这个线程的实例对象.
public static void main(String[] args) {
Thread t = new Thread(()->{
System.out.println(Thread.currentThread().getName());
},"t 线程");
t.start();
}
本文完,感谢观看,有什么错误和不足的地方请在评论区指出,一起进步,谢谢 !