1.用户线程和内核线程
用户线程(ULT):
用户程序实现,不依赖操作系统核心,应用提供创建、同步、调度和管理线程的函数来控制用户线程。不需要用户态/内核态的转换。 内核对于ULT无感知,线程阻塞则进程(包括它所有的线程)阻塞。
内核线程(KLT):
由系统内核管理的线程,内核保存线程的状态和上下文信息,线程阻塞不会引起进程的阻塞。再多处理器系统上,多线程在多处理器上并行运行。线程的创建、调度、和管理由内核完成,效率 要比ULT慢,比进程操作快
2.JVM使用的是什么线程模型?
java使用的是KLT线程模型
验证java创建的线程是内核线程:
我们在for循环中创建300个线程,然后在任务管理器中查看电脑运行对应代码之前总线程数是否增加了300来判定是否是内核线程。
package Concurrent_Programe;
/**
* @author MaZhiCheng
* @date 2020/10/14 - 18:06
*
* 通过创建三百个线程,在任务管理器中查看线程数量发现JVM创建的线程属于内核线程
*/
public class JavaUseKlt {
public static void main(String[] args) {
for(int i = 0;i < 300 ; i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true){
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
});
t.start();
}
}
}
通过运行以上代码,我们发现cpu的确增加了三百个线程,因此可以确定java创建的线程是核心线程。
3.线程为什么要池化?
线程是稀缺资源,它的创建和销毁是一个相对偏重而且消耗资源的操作,而java线程依赖于内核线程,创建需要进行操作系统状态的切换(用户态/内核态),为避免资源过度消耗需要设法重用线程执行多个任务。线程池就是一个线程缓存,负责对线程进行统一分配、调优与监控。
4.什么时候使用线程池?
- 单个任务处理时间比较短
- 需要处理的任务数量达
5.线程池的优势
- 重用存在的线程,减少线程的创建销毁的开销,提高性能。
- 提高响应速度,当任务到达时任务可以不需要等待线程的创建就能立即执行
- 提高线程的可管理性,可以进行统一的调度分配、监控和调优。
6.阻塞队列
- 在任意时刻,不管并发有多高,永远只有一个行程能够就你行队列的入队或者出队操作!也就是说是线程安全的。
- 它是一个有界队列。当队列满时只能进行出队操作,所有入队的操作必须等待,也就是被阻塞;当队列空时只能进行入队操作,所有的出队操作必须等待,也就是被阻塞。
7.线程池的工作原理
通过对于源码的阅读,发现对于线程池的状态java底层是使用一个32位的Integer的值去存储的,其中32位的高三位存储的是线程池的物种状态。
// 位移操作后高三位为111表示运行状态
private static final int RUNNING = -1 << COUNT_BITS;
// 位移操作后高三位为000表示运行状态
private static final int SHUTDOWN = 0 << COUNT_BITS;
// 位移操作后高三位为001表示运行状态
private static final int STOP = 1 << COUNT_BITS;
// 位移操作后高三位为010表示运行状态
private static final int TIDYING = 2 << COUNT_BITS;
// 位移操作后高三位为011表示运行状态
private static final int TERMINATED = 3 << COUNT_BITS;
8.线程池创建demo
package Thread_pool;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author MaZhiCheng
* @date 2020/10/14 - 17:15
*
* 线程池练习
*/
public class ThreadPoolModel1 {
public static void main(String[] args) {
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,
2,60,
TimeUnit.SECONDS,
//线程池的阻塞队列
new ArrayBlockingQueue<>(5));
//将对应的工作任务提交到对的线程池中进行运行
threadPoolExecutor.execute(new MyRunnable());
threadPoolExecutor.execute((new MyThread()));
threadPoolExecutor.shutdown();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
for(int i = 0;i < 10; i++){
Thread.currentThread().setName("线程1");
System.out.println(Thread.currentThread().getName() + "------>" + i);
}
}
}
class MyThread extends Thread{
@Override
public void run() {
for(int j = 0;j < 5;j++){
Thread.currentThread().setName("线程2");
System.out.println(Thread.currentThread().getName() + "------>" + j);
}
}
}