thread 类的基本用法-爱代码爱编程
1.线程的创建
线程有五种创建方法(一般使用lambda表达式):
(1)继承 Thread, 重写 run
class MyThread extends Thread {
public void run() {
System.out.println("重写run");
}
}
public class Demo1 {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
(2)实现 Runnable, 重写 run
class MyRunnable implements Runnable{
@Override
public void run() {
while(true) {
System.out.println("实现 Runnable, 重写 run");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Demo2 {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t= new Thread(runnable);
t.start();
while(true) {
System.out.println("你好");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(3)继承 Thread, 重写 run, 使用匿名内部类
public class Demo3 {
public static void main(String[] args) {
Thread t = new Thread(){
public void run() {
while(true) {
System.out.println("你好");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
}
}
(4)实现 Runnable, 重写 run, 使用匿名内部类
public class Demo4 {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println("你好");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
}
(5)使用 lambda 表达式
public class Demo5 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
while(true) {
System.out.println("你好");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
2.线程中断
线程中断有两种:
(1)自己定义一个标注位,作为线程是否结束的标记
public class Demo8 {
private static boolean isSign = false;//标志位
public static void main(String[] args) {
Thread t = new Thread(() -> {
while(!isSign) {
System.out.println("你好");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t线程打印完成");
});
t.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
isSign = true;
System.out.println("设置t 线程中断");
}
}
(2)使用标准库自带的标志位
public class Demo9 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
while(!Thread.currentThread().isInterrupted()) {
System.out.println("你好");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
break;
//这个地方换成break
}
}
System.out.println("t线程打印完成");
});
t.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
System.out.println("设置t 线程中断");
}
}
interrupt 方法的行为有两种情况
1.t线程在运行状态,会把Thread.currentThread().isInterrupted()这个标注位设置位true
2.t线程在阻塞状态(sleep)就不会设置标志位,而是触发一个InterruptedException,这个异常会把sleep提前唤醒,但e.printStackTrace()只是打印了日志,并没有结束循环,所以会导致继续执行,把catch里换成break就能解决了
3.线程等待
使用join,在main线程中调用t.join就是让main线程阻塞等待,等到t执行完了,main才能继续执行
public class Demo10 {
public static void main(String[] args) {
Thread t =new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("你好");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
System.out.println("main 线程join之前");
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main线程join之后");
System.out.println("不好");
}
}
执行结果:
4.线程休眠
sleep会让线程休息一会(阻塞等待)
可以看作有两个队列,像链表那样串在一起,一个是就绪队列,一个是阻塞队列,操作系统在管理这些PCB时会有多个链表.
例如我们使用了Thread.sleep(1000),就能把这个线程由就绪队列放到阻塞队列当中,不是说只阻塞1000ms,而是要至少1000ms,下一次使用的时间是由操作系统的需求来决定的,
5.获取线程实例
使用Thread.currentThread()来获取
public class Demo11 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
});
t.start();
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
}
}
代码结果: