线程的基本知识
【线程的概念】
Thread--->线程类
一:程序,进程,线程的基本区别 进程:作为资源的分配单位。 线程:调度和执行的单位。
(1)程序:指令集。【静态的】
(2)进程:操作系统cpu调度程序。【动态】在内存中分配独立的内存空间
(3)线程:一个进程中的一个执行路径
二:【进程】
(1)进程是程序的一次动态执行过程,占用特定的地址空间。
(2)每个进程都是独立的,有三部分组成,占有--->cpu【占有cpu的调度】
--->date【数据】
--->code【代码】
(3)缺点:占有cup,浪费内存空间
(4)多进程:就是操作系统同时运行多个程序,如QQ,优酷视频,百度网页
三:cpu调度 ---->cpu是解释运行进程的
---->cpu是以【时间片】的单位在操作系统中所有进程间互相进行切换。当从a进程切换到b进程,a进程执行挂起,等cpu再次切换回来,从挂起点继续往下执行。
----->【时间片】很短的时间,纳秒。正因为短,所以在我们看来,所有进程是同步的。
【线程】
---->(1)是模拟进程的。多线程是一个进程中拥有多条执行路径。每一个线程可以看成 [轻量级的进程], 而 [jvm] 就是模拟 [cpu] 在不同线程中间进行切换,解释执行线程内的代码。
----->(2)一个进程中可以有多个并行线程。每个线程是独立的。
----->(3)一个进程中的多个线程共享内存单元/内存地址空间。-->访问相同的变量和对象,从同一个堆中分配对象(通信,数据交换,同步操作)【多线程的并发问题】
----->(4)多线程是一个进程中有多个执行流。
【使线程阻塞】
一:join():合并。比如说当运行到ti.join()。ti的线程将霸占cpu调度权,直到执行结束。
二:static yield()-->那个线程调用此方法,那个线程暂时一次让出CPU调度权。至于能否暂停,实际看cpu是否去掉别的线程。我主动放弃一次,至于cpu走不走,看cpu的。
三:static sleep(long a)--->1 模拟倒计时
2 模拟网络延时
那个线程调用sleep(),该线程休眠的同时,让出cpu使用权,进入阻塞状态,直到休眠时间结束,进入就绪状态,等待cpu调度。
【线程优先级】
(1)setPriority(int )--->设置线程优先级。优先级,不代表优先运行,而是获得CPU调度权的概率大小。
tr.setPriority(tr. MAX_PRIORITY ); //将tr线程设为最高优先级int =10
tr.setPriority(tr. MIN_PRIORITY ); //将tr线程设为最低优先级--int=1
tr.setPriority(tr. NORM_PRIORITY ); //将tr线程设为默认优先级--int=5
(2)isAlive()----》判断线程的状态。线程活着返回true 线程死了返回 false
(3) currentThread () --->返回当前线程对象。 读音:可 瑞特 色润得-->cur rent Thread
(4)getName ()--->返回线程的名字 Thread.currentThread().getName()返回当前线程的名字。
【线程的创建启动】
第一种方法: A创建线程 --->让 线程类 去继承Thread类,并重写run()方法
--->run()方法内写逻辑代码--->称之为线程体
--->run()方法相当与main()方法,线程入口点。
B使用线程 --->创建类的对象,对象.start()--<线程的启动>等待cup调用解释运行。
----->不能调用run方法,如果调用run方法,那就是等于调动普通方法。
第二种方法:A创建线程--->让线程类去实现接口Runnable,并重写run()方法
----->run()方法内写逻辑代码--->称之为线程体
B启动线程--->创建真实角色--->创建线程类对象
----->创静态代理角色--->Thread bb=new Thread(Runnable a);
----->让代理角色.start()启动线程。例子 bb.start();
第二种方法线程--->实现了线程实现和线程声明的分离。
推荐使用第二种方法使用线程
原因1)避免单继承
2)共享资源
静态代理模式。
1)真实角色
2)代理角色 +持有真实角色的引用
3)二者实现相同的接口
【线程的状态】
【线程的状态】 【新生状态】---> 创建Thread对象。或Thread类的子类对象。新生状态的线程有自己的内存空间。
【就绪状态】---> 线程对象.start();等待分配到cpu或者 失去cpu使用权的状态
【运行状态】---> jvm或cpu正在运行线程内代码,自上而下。
【阻塞状态】---> 运行中时,碰到sleep();或等待IO设备等资源等一些原因,使其暂时让出cpu使用权,进入阻塞状态,等唤醒或IO设备空闲,则进入就绪状态,等待分配cpu。或者是线程休眠。wait();
【死亡状态】---> 线程中代码执行完毕正常死亡,或强制死亡,执行中途碰到stop或destroy方法(不建议使用这两个方法,前者产生异常,后者强制终止,不会释放锁)
【使线程阻塞】
一:join():合并。比如说当运行到ti.join()。ti的线程将霸占cpu调度权,直到执行结束。
二:static yield()-->那个线程调用此方法,那个线程暂时一次让出CPU调度权。至于能否暂停,实际看cpu是否去掉别的线程。我主动放弃一次,至于cpu走不走,看cpu的。
三:static sleep(long a)--->1 模拟倒计时
2 模拟网络延时
那个线程调用sleep(),该线程休眠的同时,让出cpu使用权,进入阻塞状态,直到休眠时间结束,进入就绪状态,等待cpu调度。
三、阻塞
1、join :合并线程
2、yield:暂停自己的线程 static
3、sleep:休眠,不释放锁
1)、与时间相关:倒计时
2)、模拟网络延时
【多线程同步】
一:同步线程---->是为了解决多个线程同时访问同一资源,发生的并发问题。
二:synchronized关键字
A同步方法--->在方法前加上 synchronized 关键字修饰,表示方法线程安全。public synchronized void add(int a){}--->表示此方法线程安全。
比如说:a,b,c线程访问同一资源时。
当多线程访问同一资源时,a线程获得cpu调度运行到此方法时,a线程锁住cpu调度权,直到cpu解释运行完此方法,才恢复cpu调度权的自由切换。
B同步块
synchronized(对象|类.class|this){------>syn ch ro ni zed
容易出现并发的代码块
}
锁住范围过小线程不安全
锁住范围过大降低线程效率
锁的对象不对,线程不安全
锁的范围不对,线程不安全
【线程死锁】
【死锁】---->多线程。过多的同步容易造成死锁。不是一定会造成死锁。
如果多个线程,同时操作同一份资源,而线程体内存在过个同步(同步方法和同步块),会容易造成并发问题。也就是死锁