文章目录
多线程的基本概念
1.什么是进程?
一个进程对应对应一个应用程序。例如:在windows操作系统启动Word就表示启动了一个进程。在java的开发环境下启动jvm,就表示启动了一个进程。现代的计算机都是支持多进程的,在同一个操作系统中,可以同时启动多个进程。
2.多进程有什么作用?
单进程计算机只能做一件事。对于单进程计算机来讲,在同一个时间点上,游戏进程和音乐进程是同时在运行吗?不是,因为计算机的CPU只能在某个时间点上做一件事。由于计算机将在“游戏进程”和“音乐进程”之间频繁切换执行,切换速度极高,人类感觉游戏和音乐在同时进行。
多进程的作用不是提高执行速度,而是提高CPU 的使用率
进程与进程之间的内存是独立的。
3.什么是线程?
线程是一个进程中的执行场景,线程是进程的执行单元。一个进程可以启动多个线程。线程之间相互独立的。
一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
4.多线程有什么作用?
多线程不是为了提高执行速度,而是提高应用程序的使用率。线程和线程共享“堆内存和方法去内存”,栈内存是独立的,一个线程一个栈。可以给现实世界中的人类一种错觉:感觉多个线程在同时并发执行。
并发性和并行性:并行性是指同一时刻,多条指令在多个处理器上同时执行;并发性是指同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。
归纳
一个程序运行后至少有一个进程,一个进程里可以包含多个线程,但至少要包含一个线程。
操作系统可以同时执行多个任务,每个任务就是一个进程;进程可以同时执行多个任务,每个任务就是线程。
5.java程序的运行原理
java命令会启动jvm,等于启动了一个应用程序,表示启动了一个进程。该进程会自动启动一个“主线程”,然后主线程去调用某个类的main方法。所以main方法运行在主线程中。在此之前的所有程序都是单线程的。
分析以下程序有几个线程
以下程序只有一个线程,就是主线程。
main,m1,m2,m3这四个方法在同一个栈空间中,没有启动其他任何线程。
public class Test{
public static void main(String[] args){
m1();
}
public static void m1(){
m2();
}
public static m2(){
m3();
}
public static void m3(){
System.out.println("m3....");
}
}
在java语言中实现多线程的方式
第一种方式:继承java.lang.Thread;,然后重写run方法
如何定义线程?
如何创建线程?
如何启动线程?
public class Test{
public static void mian(String[] args){
//创建线程
Thread t = new Processor();
//启动
//这段代码执行瞬间结束,告诉jvm再分配一个新的栈给t的线程
//run不需要程序员手动调用,系统线程启动之后自动调用run方法
t.start();
//t.run(); 这是普通方法调用,这样做程序只有一个线程,run方法结束后,下面程序继续执行
//这段代码在主线程中运行
for(int i=0;i<10;i++){
System.out.println("main-->"+i);
}
//有了多线程之后,main方法结束只是主线程栈中没有方法栈帧了
//但是其他线程或者其他栈中海油栈帧
//main方法结束,程序可能还在运行
}
}
//定义一个线程
class Processor extends Thread{
//重写run方法
public void run(){
for(int i=0;i<100;i++){
System.out.println("run-->"+i);
}
}
}
第二张方式:第一步:实现java.lang.Runnable;接口 第二步:实现run方法
public class ThreadTest03{
public static void main(String[] args){
//创建线程
Thread t = new Thread(new Processor()); //new Processor()代表Runable
//启动
t.start();
}
}
//推荐这种方式。因为一个类实现接口之外保留了类的继承
class Processor implements Runable{
public void run(){
for(int i=0;i<10;i++){
System.out.println("run-->"+i);
}
}
}
线程生命周期
新建(new)的线程,调用start方法进入就绪状态,就绪状态的线程有权利拿到CPU时间片,拿到时间片后进入到运行状态,run方法执行,时间片用完后,再回到就绪状态,等待获取CPU时间片,再次获得时间片后,再次进入运行状态,然后接着运行run方法,不是从头开始运行,如此反复,直到run方法执行结束,线程消亡。
运行过程中可能遇到阻塞时间,等阻塞解除后,又会回到就绪状态。
五个状态:新建,就绪,运行,阻塞,消亡
补。图
线程的调度与控制
通常我们计算机只有一个CPU,CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。在单CPU的机器上线程不是并行运行的,只有在多个CPU上线程才可以并行运行。jvm要负责线程的调度,取得CPU的使用权,目前有两种调度模型:分时调度模型和抢占式调度模型,java使用抢占式调度模型。
分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些。
三个方法
1.获取当前线程对象Thread.currentThread();
2.获取线程的名字 t.getName();
3.给线程取名 t.setName(“t1”);
public class ThreadTest{
public static void main(String[] args){
//如何获取当前线程对象?
Thread t = Thread.currentThread(); //t保存的内存地址指向的线程是“主线程对象”
//获取线程的名字
System.out.println(t.getName());
Processor p = new Processor();
Thread t1 = new Thread(p);
//给线程取名
t1.setName("t1");
t1.start();
Thread t2 = new Thread(new Processor());
t2.setName("t2");
t2.start();
}
}
class Processor implements Runnable{
public void run(){
Thread t = Thread.currentThread(); //t保存的内存地址指向的线程是“t1线程对象”
System.out.println(t.getName());
}
}
线程优先级
线程优先级主要分三种:MAX_PRIORITY(最高级-10);MIN_PRIORITY(最低级-1);NORM_PRIORITY(标准)默认-5
线程优先级高的获取的CPU时间片相对多一些
优先级:1-10
最低1
最高10
默认5
public class ThreadTest{
public static void mian(String[] args){
Thread t1 = new Processor();
t1.setName("t1");
Thread t2 = new Processor();
te.setName("t2");
System.out.println(t1.getPriority()); //默认5
System.out.println(t2.getPriority()); //默认5
//设置优先级
t1.setPriority(4);
t2.setPriority(6);
//启动线程
t1.start();
t2.seart();
}
}
class Processor extends Thread{
public void run(){
for(int i=0;i<50;i++){
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
}
1.Thread.sleep(毫秒)
2.sleep方法是一个静态方法
3.该方法的作用:阻塞当前线程,腾出CPU,让给其他线程
public class ThreadTest{
public static void main(String[] args){
Thread t1 = new Processor();
t1.setName("t1");
t1.start();
}
}
class Processor extends Thread{
//Thread中的run方法不抛出异常,所以重写run方法后,在run方法的声明位置上不能用throws
//所以run方法中的异常只能try...catch..
public void run(){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-->"+i);
try{
Thread.sleep(1000); // 让当前线程阻塞1s
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
线程同步
异步编程模型:t1线程执行t1的,t2线程执行t2的,两个线程之间谁也不等谁
同步编程模型:t1线程和t2线程执行,t1线程必须等t2线程执行结束之后,t1线程才能执行
什么时候同步?为什么要引入线程同步?
为了数据安全。尽管应用程序的使用率降低,但是为了保证数据是安全的,必须加入线程同步机制。线程同步机制使程序变成了(等同)单线程
什么条件下使用线程同步?
第一:必须是多线程环境
第二:多线程环境共享一个数据
第三:共享的数据涉及到修改操作
后续待补充