java复盘,⑩多线程

//mian方法是一个主线程,通过主线程,去调用别的线程
//怎么去确实这个程序是否是多线程呢?
//你可以用一条线,如果程序在运行的时候,能通过这条线穿起来的就是单线程

  • 1.程序:程序存储在硬盘里面,包含可以执行的计算机指令(很多的exe文件,运行指令完成某种功能)和数据静态的实体(静态代码)

  • 2.进程:指的是一个在内存中运行的程序,每一个程序都有一个独立的空间,一个应用程序可以同时运行多个

  • 进程,进程也是程序的一次执行过程,是系统运行程序的一个基本单位,系统运行一个程序即是从一个进行的

  • 创建、运行和消亡的过程。

  • 3.线程:线程是进程中的一个执行单元,负责当前进程中的程序执行,一个进程至少包含一个线程,一个

  • 进程中可以包含多个线程,这个应用程序就是多线程应用程序

  • 4.多线程:在单个程序中同时运行多个线程完成不同的功能,叫做多线程

  • (1)用户想服务器发送了一个请求,服务获取请求并且根据请求响应结果,这就是一个线程

  • (2)客户端N个请求同时去请求服务器,这就是多线程

  • (3)线程有两种调度方式:抢占式调度和

  • 分时调度:所有线程轮流使用cpu的使用权,平均分配每个线程占用cpu的时间,打饭排队的过程

  • 抢占式调度:优先让优先级高的线程使用cup,java就是使用的抢占式,挂急诊,伤重的优先,其他的继续排队的过程

  • 5.并发和并行

  • 并发:一个处理器在同一时间内同时执行多个任务(一个人同时吃两个馒头),(//并发:指的是两个或多个事件在同一时间内发生,交替执行,不好掌控没法确定谁先抢占)

  • 一个时间内有多个时间单位组成,所以说并发的多个任务在单位时间内不一定在同时进行

  • 并行:多个处理器同一时刻同时处理多个不同的任务(两个人同时吃两个馒头)(//并行:指的是两个或多个事件在同一时刻发生)

  • 这是真正同时执行的

  • 显然,并行效率比并发效率高

  • 6.为什么使用多线程?

  • 提高CPU的一个计算能力,避免资源浪费

  • 提高系统的一个响应速度

  • 一直让cpu运行着

  • 7.共享资源

  • 允许多个不同的线程访问同一个资源,最好用实现的方式

  • 8线程的分类(了解)

  • 可以分为用户线程和守护线程

  • (1)用户线程:java创建的线程默认都是用户线程

  • (2)守护线程:后台运行的线程,用于提供后台的服务(gc)

  • 区分:

  • 如果进程中还有用户线程,进程是不会终止的

  • 如果进程中只有守护线程,进程会终止

  • 9.线程的生命周期,分为5个阶段

  • 新建: 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
    就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件
    运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态, run()方法定义了线程的操作和功能
    阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出 CPU 并临时中止自己的执行,
    进入阻塞状态,堵塞是相当于挂起,临时中止不再去抢了
    注意:yield不是堵塞,他是是放再去抢
    死亡:线程完成了它的全部工作或线程被提前强制性地中止

*/

/**

  • 创建一个子线程,完成1-100之间的自然数的输出,同样主线程执行同样的操作
  • 创建多线程的第一种方式:继承Thread类
  • 1.继承Thread类
    *2.重写run方法 ,线程中实际要执行的业务逻辑
  • 3.创建子类对象
  • 4.调用线程的start()方法

//1.创建一个类继承Thread
class SubThread extends Thread{

//2.重写run方法:线程中实际要执行的业务逻辑
public void run(){
    for(int i=1;i<=100;i++){
        //获取时此线程的名字//Thread.currentThread()
        System.out.println("子线程:"+i);
    }
}

}
public class TestThread {
public static void main(String[] args) {

    //3.创建一个子类对象
    SubThread sub=new SubThread();
    SubThread sub1=new SubThread();
    //4.调用线程start()方法:启动此线程,调用相应的run方法
    sub.start();

// sub.run();//这就不是一个多线程了,没有启动多线程
//创建一个线程
sub1.start();

    for(int i=1;i<=100;i++){
        System.out.println("主线程:"+i);
    }
}

}

  • Thread类常用的方法
  • 1.void start(): 启动线程,并执行对象的run()方法
    2.run(): 线程在被调度时执行的操作,子线程需要执行的代码放到run方法中
    3.String getName(): 返回线程的名称
    4.void setName(String name):设置该线程名称
    5.static currentThread(): 返回当前线程
    6.yield():调用了此方法的线程立马释放cpu资源执行权
    (当一个线程使用了此方法后,就会把自己cup执行权释放,让给自己或着其他的线程
    ,这个让不是单纯让给别的线程,释放以后自己和别的线程再去抢cpu的执行权)
    7.join():在线程1中调用线程2的join方法,表示执行到此方法后,线程1会进入一个阻塞(停止),
    直到线程2执行完成以后,线程1在接着执行
    8.sleep():让该线程休眠,以毫秒为单位
    令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队。
    抛出InterruptedException异常

9:isAlive():判断当前线程是否存活
10。线程通信的方法

11.设置优先级 :默认是5 最小值是1,最大值是10
getPriority():获取线程的优先级值
setPriority():设置线程的优先级
MAX_PRIORITY(10);
MIN _PRIORITY (1);
NORM_PRIORITY (5);

  • 实现线程的第二种方式,
  • 1.创建一个类实现Runnable接口
  • 2.重写Runnable接口的run方法
  • 3.创建一个实现Runnable接口实现类的对象
  • 4.将实现类对象作为形参方式传递给Thread类的构造方法
  • 5.调用start方法,启动线程,并且调用实现类的对象的run方法
  • 继承方式vs实现的方式
  • Thread implements Runnable
  • 那个方式好?实现的方式优先于继承的方式
  • (1)避免了java单继承的问题
  • (2)如果多个线程要操作同一份资源(共享资源),实现的方式更加适合

class PrintNum implements Runnable{

//2.重写run方法
@Override
public void run() {
    for(int i=1;i<=100;i++){
        System.out.println(Thread.currentThread().getName()+":"+i);
    }
}

}

public class TestThread2 {

public static void main(String[] args) {
    //创建一个实现类
    PrintNum p = new PrintNum();

// p.start();会发现没有start方法
// p.run();这样写也不对,没有开启一个线程

    //怎么启动一个线程呢?必须得调用start方法
    Thread t = new Thread(p);/start方法是线程类Thread定义的方法
    t.setName("子线程");
    t.start();//启动一个线程,执行Thread对象生成的构造方法时的形参对象的run方法


    //主线程
    Thread.currentThread().setName("主线程");
    for (int i = 1; i <= 100; i++) {
        System.out.println(Thread.currentThread().getName() + ":" + i);
    }
}
  • 线程通信的三个方法;必须使用在同步代码块或同步方法中

  • wait():等待,一旦一个线程执行wait方法,就相当于释放当前的锁
    *notify()/notifyAll();唤醒wait的一个或者多个线程

  • 死锁
    不同的线程分别占用对方需要的同步资源不放弃,
    都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
    两个人去餐馆吃饭,有一碗饭,只有一双筷子,一只筷子相当于一个锁,一人拿了一支,都不肯放手

  • */
    //在开发中注意代码的抒写,减少死锁

  • 模拟火车站窗口售票,开启三个窗口同时售票,100张票

  • 使用实现的方式实现

  • 1.引起的问题:此线程是存在线程安全问题(错票、重票)

  • 原因:由于一个线程在操作共享数据的过程中,未执行完毕,另外的线程此时也参与

  • 进来了,导致共享数据出现线程安全问题

  • 2.绝对线程安全问题:线程的同步机制

  • 方式1: 同步代码块

  • synchronized (同步监视器){
    // 需要被同步的代码;(为操作共享数据的代码)
    }

1.共享数据:多个线程共同操作同一个数据
2.同步监视器:由一个对象(任何对象)来充当的,哪一个线程获得了此监视器,这个线程就
执行大括号里面的同步代码。可以理解为锁
要求:所有的线程必须共享一把锁
在实现的方式中,一般使用this来充当锁,但是在继承的实现中,不要用this
  • 方式2:同步方法
  • 将操作的共享代码的方法声明为synchronized,该方法就是一个同步方法,
  • 保证其中一个线程执行该方法时,其他线程在外等待直到此线程执行完该方法,
  • 同步方法的锁:谁调用我这个方法谁就是锁,this

static Object obj=new Object();//共享一把锁,锁可以是任何对象

热门文章

暂无图片
编程学习 ·

那些年让我们目瞪口呆的bug

程序员一生与bug奋战&#xff0c;可谓是杀敌无数&#xff0c;见怪不怪了&#xff01;在某知识社交平台中&#xff0c;一个“有哪些让程序员目瞪口呆的bug”的话题引来了6700多万的阅读&#xff0c;可见程序员们对一个话题的敏感度有多高。 1、麻省理工“只能发500英里的邮件” …
暂无图片
编程学习 ·

redis的下载与安装

下载redis wget http://download.redis.io/releases/redis-5.0.0.tar.gz解压redis tar -zxvf redis-5.0.0.tar.gz编译 make安装 make install快链方便进入redis ln -s redis-5.0.0 redis
暂无图片
编程学习 ·

《大话数据结构》第三章学习笔记--线性表(一)

线性表的定义 线性表&#xff1a;零个或多个数据元素的有限序列。 线性表元素的个数n定义为线性表的长度。n为0时&#xff0c;为空表。 在比较复杂的线性表中&#xff0c;一个数据元素可以由若干个数据项组成。 线性表的存储结构 顺序存储结构 可以用C语言中的一维数组来…
暂无图片
编程学习 ·

对象的扩展

文章目录对象的扩展属性的简洁表示法属性名表达式方法的name属性属性的可枚举性和遍历可枚举性属性的遍历super关键字对象的扩展运算符解构赋值扩展运算符AggregateError错误对象对象的扩展 属性的简洁表示法 const foo bar; const baz {foo}; baz // {foo: "bar"…
暂无图片
编程学习 ·

让程序员最头疼的5种编程语言

世界上的编程语言&#xff0c;按照其应用领域&#xff0c;可以粗略地分成三类。 有的语言是多面手&#xff0c;在很多不同的领域都能派上用场。大家学过的编程语言很多都属于这一类&#xff0c;比如说 C&#xff0c;Java&#xff0c; Python。 有的语言专注于某一特定的领域&…
暂无图片
编程学习 ·

写论文注意事项

参考链接 给研究生修改了一篇论文后&#xff0c;该985博导几近崩溃…… 重点分析 摘要与结论几乎重合 这一条是我见过研究生论文中最常出现的事情&#xff0c;很多情况下&#xff0c;他们论文中摘要部分与结论部分重复率超过70%。对于摘要而言&#xff0c;首先要用一小句话引…
暂无图片
编程学习 ·

安卓 串口开发

上图&#xff1a; 上码&#xff1a; 在APP grable添加 // 串口 需要配合在项目build.gradle中的repositories添加 maven {url "https://jitpack.io" }implementation com.github.licheedev.Android-SerialPort-API:serialport:1.0.1implementation com.jakewhart…
暂无图片
编程学习 ·

2021-2027年中国铪市场调研与发展趋势分析报告

2021-2027年中国铪市场调研与发展趋势分析报告 本报告研究中国市场铪的生产、消费及进出口情况&#xff0c;重点关注在中国市场扮演重要角色的全球及本土铪生产商&#xff0c;呈现这些厂商在中国市场的铪销量、收入、价格、毛利率、市场份额等关键指标。此外&#xff0c;针对…
暂无图片
编程学习 ·

Aggressive cows题目翻译

描述&#xff1a; Farmer John has built a new long barn, with N (2 < N < 100,000) stalls.&#xff08;John农民已经新建了一个长畜棚带有N&#xff08;2<N<100000&#xff09;个牛棚&#xff09; The stalls are located along a straight line at positions…
暂无图片
编程学习 ·

剖析组建PMO的6个大坑︱PMO深度实践

随着事业环境因素的不断纷繁演进&#xff0c;项目时代正在悄悄来临。设立项目经理转岗、要求PMP等项目管理证书已是基操&#xff0c;越来越多的组织开始组建PMO团队&#xff0c;大有曾经公司纷纷建造中台的气质&#xff08;当然两者的本质并不相同&#xff0c;只是说明这个趋势…
暂无图片
编程学习 ·

Flowable入门系列文章118 - 进程实例 07

1、获取流程实例的变量 GET运行时/进程实例/ {processInstanceId} /变量/ {变量名} 表1.获取流程实例的变量 - URL参数 参数需要值描述processInstanceId是串将流程实例的id添加到变量中。变量名是串要获取的变量的名称。 表2.获取流程实例的变量 - 响应代码 响应码描述200指…
暂无图片
编程学习 ·

微信每天自动给女[男]朋友发早安和土味情话

微信通知&#xff0c;每天给女朋友发早安、情话、诗句、天气信息等~ 前言 之前逛GitHub的时候发现了一个自动签到的小工具&#xff0c;b站、掘金等都可以&#xff0c;我看了下源码发现也是很简洁&#xff0c;也尝试用了一下&#xff0c;配置也都很简单&#xff0c;主要是他有一…
暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

项目经理,你有什么优势吗?

大侠被一个问题问住了&#xff1a;你和别人比&#xff0c;你的优势是什么呢? 大侠听到这个问题后&#xff0c;脱口而出道&#xff1a;“项目管理能力和经验啊。” 听者抬头看了一下大侠&#xff0c;显然听者对大侠的这个回答不是很满意&#xff0c;但也没有继续追问。 大侠回家…
暂无图片
编程学习 ·

nginx的负载均衡和故障转移

#注&#xff1a;proxy_temp_path和proxy_cache_path指定的路径必须在同一分区 proxy_temp_path /data0/proxy_temp_dir; #设置Web缓存区名称为cache_one&#xff0c;内存缓存空间大小为200MB&#xff0c;1天没有被访问的内容自动清除&#xff0c;硬盘缓存空间大小为30GB。 pro…
暂无图片
编程学习 ·

业务逻辑漏洞

身份认证安全 绕过身份认证的几种方法 暴力破解 测试方法∶在没有验证码限制或者一次验证码可以多次使用的地方&#xff0c;可以分为以下几种情况︰ (1)爆破用户名。当输入的用户名不存在时&#xff0c;会显示请输入正确用户名&#xff0c;或者用户名不存在 (2)已知用户名。…