目录
2.2.2.1 使用自定义的标志位结合 volatile 实现
2.2.2.2 通过 AtomiucBoolean 进行中断
一、Thread
Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。
1.1 构造方法
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");
name参数,是给线程起了一个名字。这里的名字,不影响程序执行,只是方便咱们在调试的时候,快速找到咱们关心的线程。 |
1.2 核心属性
- ID 是线程的唯一标识,不同线程不会重复
- 名称是各种调试工具用到
- 状态表示线程当前所处的一个情况,下面我们会进一步说明
- 优先级高的线程理论上来说更容易被调度到
- 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。也就是说前台线程会阻止java进程结束,后台进程不会阻止进程的结束。创建的线程默认是前台的,可以通过setDaemon设置为后台的。
- 是否存活,即简单的理解,为 run 方法是否运行结束了
- 线程的中断问题,下面我们进一步说明
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
System.out.println(Thread.currentThread().getName() + ": 我还活着");
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ": 我即将死去");
});
System.out.println(Thread.currentThread().getName() + ": ID: " + thread.getId());
System.out.println(Thread.currentThread().getName() + ": 名称: " + thread.getName());
System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());
System.out.println(Thread.currentThread().getName() + ": 优先级: " + thread.getPriority());System.out.println(Thread.currentThread().getName() + ": 后台线程: " + thread.isDaemon());
System.out.println(Thread.currentThread().getName() + ": 活着: " + thread.isAlive());
System.out.println(Thread.currentThread().getName() + ": 被中断: " + thread.isInterrupted());
thread.start();
while (thread.isAlive()) {}
System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());
}
二、线程的操作方法
2.1 启动线程
在系统中真正创建出线程需要如下步骤,而系统 API start 方法会在系统内核将对应任务进行创建:
|
启动线程的步骤如下:
- 重写 run 方法:确定线程的业务逻辑
- 调用 start 方法:让线程独立执行
2.2 线程中断机制
2.2.1 线程中断机制
一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运。所以Thread.stop、Thread.suspend、Thread.resume都已经被废弃了。 |
线程中断机制:在Java中没有办法立即停止一条线程,然后停止线程却显得尤为重要,如取消一个耗时操作。因此,Java中提供了一种用于停止线程的协商机制(中断),也即中断表示协商机制。Java并没有给中断增加任何语法,中断的过程完全需要自己实现。
若要中断一个线程,你需要手动调用该线程的 interrupt 语法,该方法也仅仅是将线程对象的中断标识设置为 true,接着你需要自己写代码不断检查当前的线程的标识位,如果为 true ,表示别的线程请求这条线程中断,此时究竟该做什么需要程序员写代码实现。
每个线程对象中都有一个中断标识位,用于表示线程是否被中断。该标识位为 true 表示中断,为 false 表示未中断。通过调用线程对象的 interrupt 方法将该线程的标识位设置为 true,可以在别的线程中调用,也可以在自己的线程中调用。
2.2.2 中断线程的常见方式
- 通过共享的标记位来进行线程间通信
- volatile 修饰的变量保证内存可见性
- AtomicBoolean 原子类保证原子性及内存可见性
- 通过 interrupt 方法进行线程间通知:仅仅设置现成的中断状态为 true,发起一个协商而不会立刻停止线程。
- interrupted:判断线程是否被中断(返回当前线程的中断状态)并清除当前中断状态(设置为false)
- 有可能两次调用的结果是不同的
- isInterrupted:判断当前线程是否被中断
2.2.2.1 使用自定义的标志位结合 volatile 实现
public class InterruptDemo {
// 保证内存可见性
static volatile boolean isStop = false;
public static void main(String[] args) {
new Thread(()->{
while(true){
if(isStop){
System.out.println(Thread.currentThread().getName()+"\t"+"stop");
break;
}
System.out.println("Hello");
}
},"t1").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(()->{
isStop = true;
},"t2").start();
}
}
注意事项:
|