第一章 多线程基础
一台主机连接若干个终端,每个终端有一个用户在使用。顺序执行的模式使得应用程序在运行时独占全部得计算机资源,资源利用率非常低。
1.1.2 线程与进程得关系
- 进程可以看成线程得容器,而线程又可以看成是进程中得执行路径。java得多线程机制是抢占式的,这表明调度机制会周期性地中断线程,将上下文切换到另一个线程。归根结底,线程就是应用程序在运行过程中,通过操作系统向cpu发起一个任务,这个任务只能访问当前进程的内存资源。
- 调用thread类的start方法,启动线程,向cpu发起请求,去执行任务。需要注意的是,执行start()方法的顺序不代表线程启动的顺序。为什么?主要因为任务的执行靠cpu,而处理器采用分片轮询方式执行任务,所有的任务都是抢占式的执行模式。任务不排序,可以设置优先级。任务被执行前,线程处于自旋等待状态。
1.2.1 线程标识
1.2.2 Thread与Runnable
1.2.3 run()与start()
- 调用Thread对象的start()方法,使线程对象开始执行任务,触发虚拟机调用当前线程对象的run方法。调用start()方法,将导致俩个线程并发运行,一个是调用start()方法的当前线程,另外一个是执行run()方法的线程。
1.2.4 thread源码分析
1.3 线程状态
线程在某个时间点,只能有一种状态。
public static void main(String[] args) {
//锁对象
Object object = new Object();
//新建t1线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
//循环10次
for (int i=0;i<10;i++){
//打印当前线程的名字+循环次数
System.out.println(Thread.currentThread().getName()+",i="+i);
//遇到第五次
if (i==5){
//使用锁对象
synchronized (object){
try {
//打印当前锁开始等待的标志
System.out.println(Thread.currentThread().getName()+"开始等待");
//使当前线程进入等待状态
object.wait();
}catch (Exception e){
}
}
}
}
}
});
//创建线程二
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
//打印当前线程开始启动
System.out.println(Thread.currentThread().getName()+"running...");
synchronized (object){
try {
//打印当前线程开始向第一个线程发送notify通知...
System.out.println(Thread.currentThread().getName()+",发送notify通知");
object.notify();
}catch (Exception e){
}
}
}
});
//启动第一个线程
t1.start();
//计算10000000次,等待一会
double d =0;
for (int i=0;i<1000000;i++){
//等待第一个线程进入wait方法
d+=(Math.PI+Math.E)/i;
}
//在主线程中读取第一个线程的状态
System.out.println(t1.getName()+"状态:"+t1.getState());
//启动第二个线程
t2.start();
}
aqs的基本原理
- 可重入锁,公平锁,非公平锁
- 公平锁:优点:所有线程都能得到资源,不会饿死在队列中。缺点:吞吐量下降,cpu唤醒阻塞线程开销大。