目录
4.实现 Runnable, 重写 run, 使用匿名内部类
1.线程创建
1.继承 Thread, 重写 run
class MyThread extends Thread{
@Override
public void run() {
while(true){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class test1 {
public static void main(String[] args) {
Thread t=new MyThread();
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.实现 Runnable, 重写 run
class MyRunnable implements Runnable{
@Override
public void run() {
while(true){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class test2 {
public static void main(String[] args) {
MyRunnable runnable=new MyRunnable();
Thread t=new Thread(runnable);
t.start();
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.继承 Thread, 重写 run, 使用匿名内部类
public class test3 {
public static void main(String[] args) {
Thread t=new Thread(){
@Override
public void run() {
while(true){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4.实现 Runnable, 重写 run, 使用匿名内部类
public class test4 {
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
5.使用 lambda 表达式
public class test5 {
public static void main(String[] args) {
Thread t=new Thread(()->{
while(true){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.线程中断
让一个线程停下来,线程的终止
本质上,线程终止办法就一种,让线程的入口方法执行完毕
2.1给线程中设定一个结束标志位
while(true){
...
}
死循环,导致入口方法无法执行完毕
解决方法
blic static boolean isQuit=false;
public static void main(String[] args) {
Thread t=new Thread( ()->{
while(!isQuit){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();//打印当前异常位置的调用栈
}
}
System.out.println("t 线程终止");
});
t.start();
//在主线程中,修改isQuit
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
isQuit=true;
}
2.2调用 interrupt() 方法来通知
interrupt方法的作用:
1.设置标志位为true
2.如果该线程正在阻塞中(比如在执行sleep)
public static void main(String[] args) {
Thread t=new Thread(() ->{
//currentThread是获取到当前线程实例
//currentThread得到的对象是t
//isInterrupted是t对象里自带的一个标志位
while(!Thread.currentThread().isInterrupted()){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
//如果要结束循环,要在catch中加break
}
}
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//把t内部的标志位设置为true
t.interrupt();
}
此时会把阻塞状态唤醒
通过抛出异常的方法让sleep立即结束
当sleep被唤醒时,sleep会自动把isInterrupted标志位给清空(true->false)
观察标志位是否清除:
如果sleep执行时,标志位为false,sleep正常休眠
如果标志位为true,无论sleep刚执行或执行一半:
1.立刻抛出异常
2.清空标志位为false
下次循环到sleep,由于标志位本身是false,就什么都不干
多线程执行顺序:
每个线程都是独立执行,执行到start方法,代码兵分两路,主线程继续执行,新线程进入到run方法执行,主线程执行完interrupt,继续往后执行,不会再到interrupt
interrupt只是通知,不是"命令",是否结束由代码来灵活控制
3.线程等待
线程之间并发执行,操作系统对线程的调度,无法确定哪个线程先执行结束
用线程等待可以规定结束顺序:如果t1线程中,调用t2.join,是让t1线程等待t2结束
Thread t=new Thread(()->{
System.out.println("t");
});
t.start();
t.join();
//在main中调用t.join,是让main线程等待t先结束,在往下执行
//在t.join执行,如果t线程还没结束,main线程会阻塞等待
System.out.println("main");
1.main线程调用tjoin的时候,如果t还执行
此时main线程阻塞,再到t执行完毕(t的run执行完了),main才从阻塞中解除,才执行
2.main线程调用t.join的时候,如果t结束
此时join不会阻塞,会立即往下执行
都保证t是先结束的
join还有一个有参的版本,填写一个参数,作为超时时间,最大等待时间
如果等待时间到达上限,还没等待,就不等了
4.线程休眠
方法 | 说明 |
public static void sleep(long millis) throws InterruptedException | 休眠当前线程 millis 毫秒 |
public static void sleep(long millis, int nanos) throws InterruptedException | 可以更高精度的休眠 |
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
//如果要结束循环,要在catch中加break
}
5.获取线程实例
方法 | 说明 |
public static Thread currentThread(); | 返回当前线程对象的引用 |
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
}