java多线程编程_Thread类_线程状态的理解(2)
【摘要】 大家好,我是bug郭,一名双非科班的在校大学生。对C/JAVA、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流作者简介:CSDN java领域新星创作者blog.csdn.net/bug…掘金LV3用户 juejin.cn/user/bug…阿里云社区专家博主,星级博主,developer.a...
大家好,我是bug郭,一名双非科班的在校大学生。对C/JAVA、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流
作者简介:
- CSDN java领域新星创作者blog.csdn.net/bug…
- 掘金LV3用户 juejin.cn/user/bug…
- 阿里云社区专家博主,星级博主,developer.aliyun.com/bug…
- 华为云云享专家 bbs.huaweicloud.com/bug…
Thread下的一些重要方法
start();
决定操作系统中是否真正创建了该线程!
如果没有执行该语句,那线程就不会执行!!!
run();
run
只是一个方法,单纯描述了该线程,就是线程内容,并不是真正的run
便没有创建好该线程!!!
中断线程
中断线程就是让线程停下来!
我们有两种方法中断线程,对应的关键就是让run
方法执行完毕!!!
还有一个特殊的main
线程,对于main
线程就需要main
方法执行完毕,线程才会结束!!!
- 手动设置标志位
自己创建一个boolean
变量, 来控制线程是否要执行结束!
public class Thread_6 {
public static void main(String[] args) {
boolean isQuit =true; //其他线程控制该标志位!
Thread t1 = new Thread(()->{
while (true&&isQuit){
System.out.println("Hello Thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
}
}
我们其他的线程可以控制该标志位isQuit
就可以中断该进程!!!
- 使用
Thread
内置标志位,进行判定
Thread.interrupted();
静态方法
Thread.currentThread();
静态方法 返回当前线程实例!
interrupt();
实例方法中断线程!
public class Thread_7 {
public static void main(String[] args) {
Thread t1 = new Thread(()->{
//
while (Thread.currentThread().isInterrupted()){
System.out.println("hello thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t1.interrupt();
}
}
当我们执行上面代码后:
代码打印了异常信息!
因为上方代码线程大部分时间是处于休眠状态阻塞!
而我们的interrupt();
方法执行后,有两种情况!
1.该进程处于就绪状态,设置标志位为true
2.该进程处于休眠状态,抛出InterruptedException
异常!
所以可以看到当执行完一次run
便抛出异常,程序中断!我们在中断之前也把异常信息打印了!
线程等待
join();
每个线程的调度顺序是无法确定的!如果我们要顺序执行某些线程就需要用到线程中的join
方法
public class Thread_9 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
while (true){
//死循环
}
});
t1.start();
t1.join(); // 让main线程等待t1线程执行完再执行!
System.out.println("执行main线程");
}
}
显然这个代码,我们无法等待t1
线程执行结束!因为该线程是个死循环无法结束!
而这样的线程等待也毫无意义!毕竟一直死等下去,程序中断在此!
join(毫秒数);
我们的线程等待可以设置毫秒数,如果到了时间,那么其他线程也不会等待该线程,不管该线程是否结束!
//main线程等待t1线程10m后再执行
public class Thread_9 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
while (true){
//死循环
}
});
t1.start();
t1.join(10_000); // 让main线程等待t1线程10m再执行!
//如果t1线程没有执行结束10m后过时不候!
System.out.println("执行main线程");
}
}
Thread.currentThread();
静态方法 返回当前线程实例!
我们通过该方法可以获取到当前线程的实例,可以知道某一时刻调用了那个线程!
public class Thread_10 {
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
//通过this获取当前实例!
System.out.println(this.getName());//获取当前线程名
}
};
t1.start();
}
}
我们不能通过Runnable
接口来获取当前线程实例,实现该接口的类只是描述了一个线程任务,并无法知道那个线程执行该任务!
sleep();
线程休眠,我们知道如果某线程调用了该方法那么该线程就处于阻塞状态!
我们之前说过,线程在操作系统中,用pcb
结构体结构来描述属性,然后用双向链表连接!
如果某一线程调用了sleep
方法,那么该线程就会在该双向链表中暂时取下,阻塞状态就无法上cpu
~
java线程状态描述
我们的java
对线程的状态又进行了进一步划分!这些状态在操作系统并没有!java
对线程状态进一步划分便于程序员调试bug
当一个线程中断了,这些java
特有的状态描述,便于我们知道该程序是在什么时期卡死的!
new
安排了工作,还未开始行动!
说明此时java
只把线程任务写好,创建好了线程对象,并没有执行start
方法,操作系统并没有创建对应的线程!
runnable
可工作的,又分为正在工作和即将工作
也就是我们已经执行了start
方法,在系统中创建好了对应的线程!一般当线程调用后,如果我们没有进行sleep
,或其他阻塞线程操作,那线程多半处于runnable
状态,在pcb
链表中就绪,随时可以上cpu
,或者已经在cpu
执行!
terminated
工作完成了
操作系统中对应的线程已经执行结束,然而java
中的线程对象还在,获取到的状态!
我们可以通过Thread
类中的getState()
的实例方法,获取当前线程的状态!
//演示上述的3种状态!
public class Thread_11 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
@Override
public void run() {
for (int i = 0; i <10; i++) {
//t1线程一直处于runnable状态!
System.out.println("hello thread!");
}
}
};
//getState();方法可以获取到线程当前状态!
//创建好了线程对象,并没有在操作系统中创建对应的线程
System.out.println("start前:"+t1.getState());
t1.start();//在操作系统中创建好了对应的线程!
//runnable状态!
System.out.println("start后:"+t1.getState());
//等待t1线程执行结束!
t1.join();
//获取到terminated 结束状态!
System.out.println("t1结束:"+t1.getState());
}
}
表示排队等待其他事情
下面的3个线程状态都是阻塞状态,但是互相又有些区别!
blocked
当前线程在等待锁,导致的阻塞,后面我们会介绍synchronize
而导致的阻塞
public class Thread_13 {
private static int i=0;
public synchronized static void increase(){
for (int j = 0; j <100_0000 ; j++) {
i++;
}
}
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
increase();
}
};
Thread t2 = new Thread(){
@Override
public void run() {
increase();
}
};
t1.start();
t2.start();
//线程t1和t2都要执行increase方法!当t1执行时,那么t2就要等待锁!
System.out.println("t1:"+t1.getState());
System.out.println("t2:"+t2.getState());
}
}
waiting
当前线程在等待唤醒,导致的阻塞!
private static int count;
public static void main(String[] args) {
//waiting : 等待唤醒导致的阻塞态!
//锁对象
Object locker = new Object();
Thread t1 = new Thread(()->{
synchronized(locker){
for (int i = 0; i < 100_0000; i++) {
count++;
}
System.out.println("count:"+count);
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
locker.notify();//唤醒!
}
});
Thread t2 = new Thread(()->{
synchronized (locker){
try {
locker.wait();//等待唤醒!
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i <100_0000 ; i++) {
count++;
}
System.out.println("count:"+count);
}
});
t1.start();
t2.start();
System.out.println("t1:"+t1.getState()+" t2:"+t2.getState());
}
timed_waiting
代码调用了sleep
就会进入timed_waiting
阻塞状态,或者join
超时
public class Thread_12 {
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
while (true){//这个线程大部分时间处于阻塞状态!
System.out.println("hello thread");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
System.out.println("start:"+t1.getState());
System.out.println("sleep:"+t1.getState());
}
}
我们再画一个图便于大家理解上述的各种状态!
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)