多线程 文章目录多线程的基本概念1.什么是进程2.多进程有什么作用3.什么是线程4.多线程有什么作用归纳5.java程序的运行原理在java语言中实现多线程的方式第一种方式继承java.lang.Thread;然后重写run方法第二张方式第一步实现java.lang.Runnable;接口 第二步实现run方法线程生命周期线程的调度与控制线程优先级线程同步多线程的基本概念1.什么是进程一个进程对应对应一个应用程序。例如:在windows操作系统启动Word就表示启动了一个进程。在java的开发环境下启动jvm,就表示启动了一个进程。现代的计算机都是支持多进程的在同一个操作系统中可以同时启动多个进程。2.多进程有什么作用单进程计算机只能做一件事。对于单进程计算机来讲在同一个时间点上游戏进程和音乐进程是同时在运行吗不是因为计算机的CPU只能在某个时间点上做一件事。由于计算机将在“游戏进程”和“音乐进程”之间频繁切换执行切换速度极高人类感觉游戏和音乐在同时进行。多进程的作用不是提高执行速度而是提高CPU 的使用率进程与进程之间的内存是独立的。3.什么是线程线程是一个进程中的执行场景线程是进程的执行单元。一个进程可以启动多个线程。线程之间相互独立的。一个线程可以创建和撤销另一个线程同一个进程中的多个线程之间可以并发执行。4.多线程有什么作用多线程不是为了提高执行速度而是提高应用程序的使用率。线程和线程共享“堆内存和方法去内存”栈内存是独立的一个线程一个栈。可以给现实世界中的人类一种错觉感觉多个线程在同时并发执行。并发性和并行性并行性是指同一时刻多条指令在多个处理器上同时执行并发性是指同一时刻只能有一条指令执行但多个进程指令被快速轮换执行使得在宏观上具有多个进程同时执行的效果。归纳一个程序运行后至少有一个进程一个进程里可以包含多个线程但至少要包含一个线程。操作系统可以同时执行多个任务每个任务就是一个进程进程可以同时执行多个任务每个任务就是线程。5.java程序的运行原理java命令会启动jvm等于启动了一个应用程序表示启动了一个进程。该进程会自动启动一个“主线程”然后主线程去调用某个类的main方法。所以main方法运行在主线程中。在此之前的所有程序都是单线程的。分析以下程序有几个线程以下程序只有一个线程就是主线程。 mainm1m2m3这四个方法在同一个栈空间中没有启动其他任何线程。 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 i0;i10;i){ System.out.println(main--i); } //有了多线程之后main方法结束只是主线程栈中没有方法栈帧了 //但是其他线程或者其他栈中海油栈帧 //main方法结束程序可能还在运行 } } //定义一个线程 class Processor extends Thread{ //重写run方法 public void run(){ for(int i0;i100;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 i0;i10;i){ System.out.println(run--i); } } }线程生命周期新建new的线程调用start方法进入就绪状态就绪状态的线程有权利拿到CPU时间片拿到时间片后进入到运行状态run方法执行时间片用完后再回到就绪状态等待获取CPU时间片再次获得时间片后再次进入运行状态然后接着运行run方法不是从头开始运行如此反复直到run方法执行结束线程消亡。运行过程中可能遇到阻塞时间等阻塞解除后又会回到就绪状态。五个状态新建就绪运行阻塞消亡补。图线程的调度与控制通常我们计算机只有一个CPUCPU在某一个时刻只能执行一条指令线程只有得到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默认5public 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 i0;i50;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 i0;i10;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线程才能执行什么时候同步为什么要引入线程同步为了数据安全。尽管应用程序的使用率降低但是为了保证数据是安全的必须加入线程同步机制。线程同步机制使程序变成了等同单线程什么条件下使用线程同步第一必须是多线程环境第二多线程环境共享一个数据第三共享的数据涉及到修改操作后续待补充