线程运行原理
多线程
栈帧是以线程为基本单位,每个线程都有自己的栈内存,有自己的多个栈帧
因为某些原因cpu不再执行当前的线程,转而执行其他线程。
当线程上下文切换时,要保证当前线程的状态。并恢复另一个线程的状态,JAVA中对应的概念就是程序计数器,作用是记录了下一条JVM指令的执行地址,是线程私有的。
方法名 | static | 功能说明 | 注意 |
start() | 启动一个新的线程 | 只能调用一次,多次会出现异常 | |
run() | 新的线程启动后会调用这个方法 | 如果实现了Runnable参数。则线程启动后会调用Runnable的run方法 | |
join() | 等待线程运行结束 | ||
join(long n) | 等待线程运行结束,最多等n秒 | ||
getId() | 获取线程长整型的id | id唯一 | |
getName() | 获取线程名 | ||
setName(String) | 修改线程名 | ||
getPriority() | 获取线程优先级 | ||
setPriority(int) | 设置线程优先级 | java中规定优先级1-10级,较大的优先级能提高调度几率 | |
getState() | 获取线程状态 | Java中线程状态是用6个,分别是NEW... | |
isInterrupted() | 判断是否被打断 | 不会清除标记(打断标记) | |
interrupt() | 打断线程 | 如果打断线程正在sleep,waitjoin会导致被打断的线程抛出InterruptedException,并清除打断标记。如果打断正在运行的线程,则会设置打断标记。park的线程被打断也会被设置打断标记 | |
interrupted() | static | 判断当前线程是否被打断 | 会清除标记(打断标记) |
currentThread() | static | ||
isAlive() | 线程是否存活 | ||
sleep(long n) | static | 让当前执行的线程,休眠n毫秒,休眠时间让出CPU时间片 | |
yield() | static | 提示让出CPU |
1.打断阻塞
打断sleep,wait,join的线程,会设置标记为false
打断正在运行时的线程,就会标记为true
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
f1();
}
});
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
f2();
}
});
thread.start();
thread.interrupt();
System.out.println("线程的状态"+thread.isInterrupted());
thread.join();
}
public static void f1(){
int a=1;
System.out.println(a);
}
2.打断正常运行
public class StackTest {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
while (true){
}
}
});
thread.start();
thread.interrupt();
System.out.println("线程的状态"+thread.isInterrupted());
thread.join();
}
public static void f1(){
int a=1;
System.out.println(a);
}
}
注意看,虽然打断成功了,但是线程并没有停止。这是因为这个打断只是告诉这个线程我要打断你了。具体停不停还得是看那个线程的自己的实现。
完整版
public class StackTest {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
while (true){
Thread thread1=Thread.currentThread();
if(thread1.isInterrupted()){
System.out.println("线程被打断了");
break;
}
}
}
});
thread.start();
thread.interrupt();
System.out.println("线程的状态"+thread.isInterrupted());
thread.join();
}
public static void f1(){
int a=1;
System.out.println(a);
}
在一个线程T1中如何优雅的中止线程T2?优雅就是给T2一个料理后事的机会
使用线程对象的stop()方法停止线程
stop()方法会真正的杀死线程。如果这时线程锁住了共享资源,那么被它杀死后就再也没有机会释放锁,其他线程将永远无法获取锁。
使用System.exit(int)方法停止线程。
目的:仅仅要停止一个线程,你这全停了。
package algorithm;
import lombok.extern.slf4j.Slf4j;
public class Test3 {
public static void main(String[] args) throws InterruptedException {
TowPhaseTermination tpt=new TowPhaseTermination();
tpt.start();
Thread.sleep(10000);
tpt.stop();
}
}
class TowPhaseTermination{
private Thread monitor;
public void start(){
monitor=new Thread(()->{
while (true){
Thread current= Thread.currentThread();
if(current.isInterrupted()){
System.out.println("料理后事...");
break;
}
try {
Thread.sleep(2000);
System.out.println(current.getName()+"执行监控记录");
} catch (InterruptedException e) {
e.printStackTrace();
//重新设置打断标记
current.interrupt();
}
}
});
monitor.start();
}
public void stop(){
monitor.interrupt();;
}
}