线程的创建
这个在前面的文章中,有详细的创建方法,共有五种.
线程中断
怎么让线程提前中止?
核心就是让run方法能够提前结束!!!所以为了让线程结束,引入了标志位
这里有两种方法
第一种就是弄一个标志位
public class TreadDemo5 {
private static boolean isQuit = false;//标志位
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (!isQuit){
System.out.println("xiaodong");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
Thread.sleep(1000);
System.out.println("让线程结束");
isQuit = true;
}
}
通过上述的代码,就可以让线程结束掉!
具体的结束时间,取决于另一个线程中何时修改isQuit的值.
注意,代码中,isQuit为什么要写在main外,不能写在main内???
因为lambda表达式的本质是"函数式接口"->“匿名内部类”,然后内部类,访问外部类成员这个事本就是可以的!!
第二种方法,就是用Thread.currentThread();
这个的操作就是获取当前线程实例,哪个线程调用,就获取哪个线程的实例(类似于this)
public class TreadDemo5 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()){
System.out.println("xiaodong");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
Thread.sleep(1000);
System.out.println("让线程结束");
t.isInterrupted();
}
}
这个代码的本质,就是Thread实例内部自带的标志位,来替代前面手动创建的isQuit变量了
但是这个有一个问题,就是其中的Thread.sleep(1000);这里会有报错日志!!!
具体的原因是: 在执行sleep的过程中,会调用interrupt,大概率sleep的睡眠时间并没有到,就被唤醒了,然后被提前唤醒会做两件事
1>抛出InterruptedException,紧接着就会被catch获取到,
2>清除Thread对象的isInterrupted标志位
线程等待
多个线程的执行的顺序不是一定的,是随机调度,抢占式执行的
但是虽然线程底层的调度是无序的,但可以在应用程序中通过一些api,来影响线程执行的顺序
jion就是一种方法.
public class TreadDemo5 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("工作中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("线程执行结束");
});
t.start();
//这个操作就是等待线程
t.join();
System.out.println("期望在t线程结束后打印");
}
}
这个代码中,是在main线程中调用了t.join();
这是让main线程等待t线程结束,(注意这个谁等谁一定要分清楚)
这个在执行join的时候,就会看t线程是否在运行
如果t在运行中,main线程就会阻塞
如果t运行结束,main就会从阻塞中恢复过来.
注意,join代表的不是确定执行顺序,而是结束的顺序!!!
获取线程引用
用到的是Thread.currentThread()获取到当前线程的引用(Thread的引用)
class MyThread extends Thread{
@Override
public void run() {
//在这个代码中,如果想获取线程引用,用this即可
System.out.println(this.getId() + " ," + this.getName());
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t1 = new MyThread();
Thread t2 = new MyThread();
t1.start();
t2.start();
}
}
像这上面的代码中,是继承Thread,直接使用this就可以拿到线程实例
如果是Runnable或者lambda表达式,this就无能为力了,此时的this就不会再指向Thread对象了,就只能使用 Thread.currentThread();
public class TreadDemo5 {
public static void main(String[] args){
Thread t1 = new Thread(() ->{
Thread t = Thread.currentThread();
System.out.println(t.getName());
});
Thread t2 = new Thread(() ->{
Thread t = Thread.currentThread();
System.out.println(t.getName());
});
t1.start();
t2.start();
}
}
就是这个代码一样,里面使用Thread.currentThread();
线程的休眠
线程的休眠其实就是我们前面看到的Thread.sleep();这个操作,这个括号里面填写的是时间,毫秒为单位!
在使用这个Thread.sleep();的时候记得try catch一下异常,不然会报异常错误!!!