深入理解线程的原理和用法

Java中的线程:
程序、进程和线程
1程序是一段静态的代码,它是应用程序执行的蓝本
2进程是程序的一次动态执行过程。它对应了从代码加载、执行到执行完毕的一个完整过程。作为蓝本的程序可以被多次加载到系统的不同内存区域分别执行,形成不同的进程。
3线程是进程内部单一的一个顺序控制流。一个进程在执行过程中,可以产生多个线程。每个线程也有自己产生、存在和消亡的过程。
使用线程的目的就是 增加并发性。
就绪态:1分配指令计数器pc 2在jvm中拥有独立的虚拟机栈、本地方法栈和PC寄存器(可以随时占用处理机)会跟主线程争夺处理机 主方法执行完毕 就主线程就执行完 jvm中就绪池中还有两个线程
处于阻塞态的资源 :释放jvm的空间 不会征用处理机
开始状态线程 :在jvm中开辟空间
(1) Java线程的调度策略 依赖系统的调度策略 没有规律可言!
① 随机调度(随机从就绪态中拿一个)
② 一旦线程在执行,只有当前线程执行完或者执行到某个可停止点,才会调度其他线程。
③ C语言,windows系统底层:先来先服务,时间片轮转
后台线程:前台线程执行完毕 后台线程将自动结束
线程是不安全的: 会出现“100-40=80”的情况 所以需要尽可能避免这种情况currentThread当前线程对象的地址
(1) currentThread.getName:当前线程对象的线程名
(2) mathine1.setName(“m1”);设置线程名
(3) SetPriority:设置优先级
① 优先级:有三种

  1. 十级:MAX_PRIORITY
  2. 五级:默认NORM_ PRIORITY=5
  3. 一级:MIN_PRIORITY
    ② 由主线程创建的线程默认和主线程相同
  1. Yield():(当某一个线程执行,不会主动放弃处理机)主动放弃处理机,从运行态直接进入就绪态
    (1) 当某个线程占用占用处理机,主动放弃处理机,给同优先级或更高优先级的线程占用处理机的机会,从运行态直接进入就绪态。
  2. setDaemon():设定为后台线程(必须在该线程启动(start())之前)
    (1) 所有前台进程结束后,后台线程自动终止
    在这里插入图片描述
public class Mathine extends Thread{
  public void run(){
  	   
    for ( int a=0;a<10;a++){
                                                
   	System.out.println(currentThread().getName()+":"+a);//拿到线程的地址  然后再拿到线程的名字
       try {			//阻塞态条件满足后 会处于就绪态 
            sleep(100);//休眠期  处于阻塞态:1主动放弃处理机sleep  2 等待io的操作 等待用户输入数据 3执行某段代码的时候发现代码上锁了 4处于对象阻塞池 
           }catch (InterruptedException e) {throw new RuntimeException(e);
           }
         }
        }
   
      public static void main(String[] args) {//通过main方法进行主线程,在栈中开辟主方法栈帧空间开辟主线程的run方法栈帧。主方法执行完毕,主线程也会结束。
        Mathine mathine1 = new Mathine();//在栈区 给mathine1线程 开辟 run方法栈帧
        Mathine mathine2 = new Mathine();//在栈区 给mathine1线程 开辟 run方法栈帧
            //mathine1.setName("m1");
           // mathine2.setName("m2");
   	    mathine1.setPriority(Thread.MAX_PRIORITY);//设置线程的优先级  高优先
           mathine2.setPriority(Thread.MIN_PRIORITY);//设置线程的优先级   低优先
   	   // System.out.println("Priority of m1:"+mathine1.getPriority());
        // System.out.println("Priority of m2:"+mathine2.getPriority());
   	    mathine1.start();  //执行mathine1线程 栈的run()方法空间  此时处于就绪状态(1在栈中分配了空间 ,2分配指令计数器pc,可以随时占用处理机)
           mathine2.start();//mathine2线程栈的 run方法空间 此时处于就绪状态
           mathine1.run(); //开辟主线程的run方法栈帧。主线程主动执行了 mathine1的run 方法 Thread.currentThread().getName()//得到线程地址跟线程名

线程的3中常用创建方式
第一种:继承Thread这个类 , 然后复写该类的run方法, 通过new 该类 调用start方法来开启线程。
第二种:
**加粗样式

第三种:通过自定义线程池来调用
线程池可以自定义创建 也可以直接调用API创建
在这里插入图片描述

我们通常通过ThreadPoolExecutor来创建线程池,具体细节就不细说了
在这里插入图片描述

通过调用execute()方法来开启线程
在这里插入图片描述

这三种创建线程的方式推荐通过线程池,因为通过线程池固定了线程的数量,不会因为线程大量的新生死亡操作而消耗CPU。

在这里插入图片描述

这两个方法的区别:如果直接调用线程的run()方法,会在当前线程执行,调用线程的start方法则会在新的线程执行。

在这里插入图片描述

为什么会出现线程不安全的问题
对于多个线程操作堆中的同一个对象,因为线程是独立的,对象是共享的,而且JVM采用了分片方式,即每个线程只会执行jvm给你分配的时间片,如果时间耗尽或者到了安全停止点,那么该线程就会让出资源,给其他线程。这就导致,线程执行语句不会全部执行完,解决方法,让所有执行语句看成一个整体,只有整体执行完毕才会让出资源。即使用 synchronized

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值