一、线程创建
1.继承Thread,重写run
package demo1;
//继承 Thread, 重写 run
class MyThread extends Thread{
@Override
public void run() {
System.out.println("继承 Thread, 重写 run");
}
}
public class Demo1 {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
2.实现Runnable,重写run
package demo2;
//实现 Runnable, 重写 run
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("实现 Runnable, 重写 run");
}
}
public class Demo2 {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
3.继承Thread,重写run,使用匿名内部类
package demo3;
//继承 Thread, 重写 run, 使用匿名内部类
public class Demo3 {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run() {
System.out.println("继承 Thread, 重写 run, 使用匿名内部类");
}
};
t.start();
}
}
4.实现Runnable,重写run,使用匿名内部类
package demo4;
//实现 Runnable, 重写 run, 使用匿名内部类
public class Demo4 {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("实现 Runnable, 重写 run, 使用匿名内部类");
}
});
t.start();
}
}
5.使用 lambda 表达式(推荐)
package demo5;
//使用 lambda 表达式
public class Demo5 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> System.out.println("使用 lambda 表达式"));
Thread t2 = new Thread(() -> {
System.out.println("使用 lambda 表达式");
});
t1.start();
t2.start();
}
}
二、线程休眠
Thread.sleep(1000);
//休眠一秒
三、获取线程实例
Thread.currentThread();
//用来获取当前线程的实例
四、线程中断
在Java中,要销毁/终止一个线程,只能想办法让 run 方法尽快执行结束。
1.手动创建标志位
线程持续工作很久,往往是因为其中有循环语句,想要让 run 方法执行结束,就是要让循环语句尽快退出。因此我们可以在代码中手动创建出标志位,来作为 run 方法执行结束的标志。
package demo6;
public class Demo6 {
private static boolean isQuit = false;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (!isQuit){
System.out.println("线程正在工作");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程工作结束");
});
t.start();
Thread.sleep(5000);
isQuit = true;
}
}
运行结果:
这种方法的确可以实现线程中断,但是需要手动创建标志位,而且当线程内部处于 sleep(阻塞) 状态时,不能及时响应。
2.使用 Thread 内部标志位
Thread 类内部有一个标志位,这个标志位可以用来判定线程是否结束,即使内部处于阻塞状态,也能被唤起。
package demo6;
public class Demo6 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()){
// Thread.currentThread()可以获取当前线程的实例,相当于t
// t.isInterrupted()获取内部的标志位
System.out.println("线程正在工作");
try {
Thread.sleep(1000);
// 正常情况下,sleep 的休眠期到了才能唤醒,但是 interrupt() 会使 sleep 内部触发一个异常,从而提前被唤醒。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程工作结束");
});
t.start();
Thread.sleep(5000);
t.interrupt(); //把对象内部的标志位设置为 true
}
}
运行结果:
观察运行结果我们不难发现,主线程执行完 t.interrupt() 后,异常确实出现了,但是t线程仍在继续工作。这是因为 interrupt() 唤醒线程后,sleep 方法抛出异常,同时会自动清除刚才设置的标志位,使得标志位的效果像是没有生效。这样的设定是为了能让我们自己决定接下来如何处理。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//1.循环继续正常执行,相当于什么都没发生
e.printStackTrace();
//2.加上一个break; 相当于让线程立即结束
//break;
//3.可以做点其他的事情,然后再结束
//(其他的事情)
//break;
}
五、线程等待
为了控制线程执行的顺序,让一个线程等待另一个线程执行结束后再执行
//在主线程中调用
t.join(); //还可以设置超时时间,如 t.join(1000) 就表示最多等待一秒。
//此时主线程等待t线程先结束
标签:基本,run,Thread,void,用法,线程,重写,public From: https://blog.csdn.net/2301_76907962/article/details/142979417工作过程:
- 如果t线程正在工作中,此时调用 join 就会发生阻塞,直到超时或t线程执行结束。
- 如果t线程已经执行结束,此时调用 join 就会直接返回,不会涉及到阻塞。