并发编程系列之线程基础知识回顾
Posted smileNicky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程系列之线程基础知识回顾相关的知识,希望对你有一定的参考价值。
并发线程的知识是很重要而且比较杂的知识点,所以需要花不少时间用于整理。本博客整理线程的一些比较重要而且比较基础的知识点,帮忙读者入门,注意只是学习并发编程的一些基础点,要系统学习的是需要多看看书籍还是花不少时间整理的。本博客是在参加培训后做的笔记,仅供学习参考
问题1、使用多线程的目的是什么?
充分利用cpu资源,可以并发的处理任务
问题2、单核cpu不适合多线程?
单核cpu也是适合多线程的,单核的cpu系统中,一个进程中是允许有多个线程的。而且单线程在等待io时,cpu就空闲出来了
问题3、线程什么时候让出cpu?
- 线程阻塞时,使用wait、await等待io时候
- 线程sleep时,使用了sleep
- 线程yield时候,使用了yield
- 线程结束的情况
问题4、什么是线程?
线程是进程的一部分,可以理解为一条代码的执行流,完成一组代码的执行,这组代码往往被称之为一个任务
问题5、CPU是做什么工作的?
从执行代码角度,也可以说CPU就是执行代码的
问题6、如何正确stop线程
对于stop线程,读者可能会想能不能用Thread.stop
?这种方法是绝对不允许的,在Oracle官网也对比进行了比较详细的说明,https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/doc-files/threadPrimitiveDeprecation.html
归纳起来就是这样的, 线程不安全 使用stop会释放所有持有的锁,会导致被保护的资源不一致,使得程序结构不确定
ok,然后如何正确的stop线程?
- 1、使用volatile boolean变量来标记线程是否stop
private volatile stop = false;
public void doWork() {
Thread t = new Thread(() -> {
while (!stop) {
// do someting
}
});
}
public void doStop() {
stop = true;
}
- 2、使用线程的
interrupt()
方法
Thread.interrupt();
- 3、对于blocking io的处理,使用interruptibleChannel来替代blocking io
问题7、创建线程的方法有多少种?
创建线程的方法从源码角度是只有一种的,也即new Thread
,不过实现方式语法上来说就有很多种,比如实现Runnable接口,或者是通过继承Thread类实现,或者是通过Callable来实现,或者是通过线程池来创建等等,这种方法只是语法上的不同,要从源码角度来说就只有一种,所以面试时候可以列举这些方法,然后和面试官说从源码角度上来只有一种,详情可以参考我上篇博客并非编程系列之创建线程的方法有多少种?
问题8、线程有哪几个状态?
在idea里,用快捷键看一下Threa的状态,如图:
所以,线程的状态是有这几种的:
- NEW(初始):也即新建一个线程对象,这个过程还没调用start方法
Thread t = new Thread(() -> {
System.out.println(Thread.currentThread().getName());
});
System.out.println("创建线程后状态:" + t.getState());
创建线程后状态::NEW
- RUNNABLE(运行):Java线程池中将(ready)就绪和(running)运行中两种状态统称为RUNNABLE,线程调用了start就会放在线程池中,处于就绪ready状态,等到分配到时间片后才变为运行runing状态
Thread t = new Thread(() -> {
System.out.println(Thread.currentThread().getName());
});
t.start();
System.out.println("Thread.start()之后的状态:" + t.getState());
Thread.start()之后的状态:RUNNABLE
- BLOCKED(阻塞):表示线程阻塞于锁。线程抢不到锁就会出现这种状态
Thread t1 = new Thread(() -> {
synchronized (ThreadStatusExample_Synchronized.class) {
System.out.println("t1抢到锁");
}
});
synchronized (ThreadStatusExample_Synchronized.class) {
t1.start();
Thread.sleep(1000L);
System.out.println("t1抢不到锁时的状态:"+t1.getState());
}
t1抢不到锁时的状态:BLOCKED
t1抢到锁
- WAITING(等待):WAITING状态,线程进入等待状态
public static void main(String[] args) throws Throwable {
Thread t1 = new Thread(() -> {
LockSupport.park();
});
t1.start();
Thread.sleep(2000L);
System.out.println("t1 被park后的状态:" + t1.getState());
LockSupport.unpark(t1);
}
t1 被park后的状态:WAITING
- TIMED_WAITING(超时等待):这种timed_awiting不同于waiting,可以在指定的时间后自行返回
private static volatile boolean running = true;
public static void main(String[] args) throws Throwable{
Thread t = new Thread(() -> {
while (running) {}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
// volatile boolean标志的变量设置为false,让子线程退出循环
running = false;
Thread.sleep(1000L);
System.out.println("Threa.sleep之后的状态:" + t.getState());
}
Threa.sleep之后的状态:TERMINATED
- TREMINATED(终止):这个状态表示线程已经执行完成
这种情况,可以用Thread.sleep,等到线程执行完成就会打印出来
问题9、线程状态的转换
问题10、Runnable和Callable对象是线程?
Thread才是线程对象,Runable和Callable可以理解为线程任务,需要开发者自己去实现接口
以上是关于并发编程系列之线程基础知识回顾的主要内容,如果未能解决你的问题,请参考以下文章