java重点基础:线程和同步锁和线程通信
学习线程的主要知识点概要如下:
进程和线程的区别:
* 1.进程:操作系统而言,进程就是程序,多进程就是多个程序同时执行
* 一个进程包含一个~多个线程,每一个进程都有自己的代码和运行空间,进程之间切换开销较大,进程是资源分配的最小单位
* 2.线程:程序中的顺序流,多线程:一个程序中的多个顺序流同时执行
* 一系列线程共享代码和数据空间,每个线程都有自己的程序计数器,线程之间切换开销较小,线程是cpu调度的最小单位
线程和进程的状态: 新生 就绪 运行 阻塞 终止 ![](/assets/blank.gif)
CPU只会给就绪状态和运行状态的线程时间片,不会给阻塞状态的
新生状态:线程创建完就是新生状态
就绪状态:当调用start()方法就是进入就绪状态,等待CPU给时间片,不给时间片不执行,时间片用完了也进入就绪状态
运行状态:当CPU给之间片真正执行的时间,当时间片用完了,继续回到就绪状态
阻塞状态:在阻塞状态时,CPU必定不会给时间片,因为被阻塞了,必须等待其进入到就绪状态才行
终止状态:线程被终止了
如何进入到就绪状态
* 1.start()
* 2.阻塞解除
* 3.线程切换,被切换的线程进入到就绪状态
* 4.yield() 礼让线程
如何进入到阻塞状态
1.sleep(毫秒数) 方法 当时间结束了就自动回到就绪状态
2.join()方法 当被插队的结束了才能回到就绪状态
3.wait()方法 一直等待,直到被notify()方法唤醒才能进入到就绪状态
thread.join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程t的join()方法,直到线程t执行完毕后,才会继续执行线程B。
- t.join(); //在B线程中使调用线程 t 在此之前执行完毕。
- t.join(1000); //在B线程中,等待 t 线程,等待时间是1000毫秒
注意:如果线程被生成了,但还未被起动,调用它的 join() 方法是没有作用的,将直接继续向下执行
如何让一个线程进入到终止状态
1.正常执行完毕
2.destroy() |stop() 已过时
3.通过标识手动判断
sleep() 线程休眠
* 1.模拟网络延迟
* 2.放大问题的可能性
* 抱着资源睡觉,同步的对象资源,让出cpu的资源
yield() 有这个方法的线程是高风亮节,礼让线程
当A,B线程同时开启时候,当A中有yield()方法,在执行A中的方法时候,遇到yield方法,这个线程就回到就绪状态,再次调用的时候就会接着上次没有执行的代码向下执行!!!!!!!!!!!!!!!!!!
如何创建一个线程
* 1) 继承Thread,重写run()方法
* 1)在run()方法中定义线程体
* 2)开启: 使用start()方法开启线程
* 2) 实现Runnable接口,重写run()方法 推荐
* 3) 实现Callable接口,重写call()方法
第一种:单继承Thread类,重写run方法:
public class ThreadDemo01 extends Thread{//多线程的线程体@Overridepublic void run() {for(int i=1;i<=20;i++){System.out.println("一遍吃饭...");}}public static void main(String[] args) {//开启多线程 创建线程ThreadDemo01 th=new ThreadDemo01();th.start(); //开启线程//th.run(); 注意:这是方法的调用,不是多线程的开启for(int i=1;i<=20;i++){System.out.println("一遍说话...");}//th.start(); 放在这里的话:主线程中代码执行完毕,只剩下一个th线程,看不到线程切换的效果}
}
第二种,实现runnable接口,避免单继承的局限性,推荐使用
public class ThreadDemo02 implements Runnable{//定义线程体的方法,当被调用的时候,会逐行执行里面的代码@Overridepublic void run() {for(int i=1;i<=10;i++){System.out.println("一遍敲代码...");}}public static void main(String[] args) {ThreadDemo02 th=new ThreadDemo02();//创建线程//开启线程Thread t=new Thread(th); //因为开启线程的方法在Thread类中,Thread做为代理类出现,静态代理t.start();for(int i=1;i<=10;i++){System.out.println("一遍陪女朋友...");}}
}
练习:
* 模拟12306
* 需求: 100张票,3个人买完
* 资源共享: 100张票
下面的代码会造成多人抢到一张票的问题,待优化
在创建线程的时候Thread th1=new Thread(web,"王冬冬");th1作为代理出现,web指的是代理哪一个线程,第二个指的是线程名
public class Web12306_03 implements Runnable{//成员 资源int tikets=100;@Overridepublic void run() {//循环买票while(true){if(tikets<=0){break;}try {Thread.sleep(1); //线程睡眠100ms} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在购买第"+tikets--);}}public static void main(String[] args) {Web12306_03 web=new Web12306_03();//开启三个线程Thread th1=new Thread(web,"王冬冬");Thread th2=new Thread(web,"王宇晨");Thread th3=new Thread(web,"郭友波");th1.start();th2.start();th3.start();}
}
线程的优先级
* 线程的优先级: 提高优先执行的可能性,但是不一定就会先执行
* void setPriority(int newPriority) 更改线程的优先级。
* 1~10 1最小 10最大
* Thread.NORM_PRIORITY 5
* Thread.MAX_PRIORITY 10
* Thread.MIN_PRIORITY 1
可以直接输入数字 th.getPriority() //5/10/1/... th.getState()//获得状态 new / runnable time_waiting
synchronized 同步锁
锁方法简单,但是效率低,因为锁的是整个,要效率可以锁代码块
* 线程安全:
* 多个线程同时操作同一个资源的时候,才可能会出现线程安全问题,例如上述的抢票
*
* 通过同步synchronized关键字控制线程安全:
* 同步方法
* 静态方法
* 成员方法
* 同步块 synchronized(类的class对象|this|资源){代码} 锁住的必须是不可变的
* 类: 类名.class 一个类的Class对象 一个类只有一个Class对象 this和static不能同时使用
*
* 锁要锁着不变的东西,会变的锁不住,锁住资源
* 同步的范围 {} 中的内容太大,效率低,同步的范围太小,锁不住
* 单例模式:懒汉式
public static synchronized Single newInstance(){System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");if(single==null){single=new Single();}return single;}
public static Single newInstance(){System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");synchronized (Single.class) { //控制多线程排队执行if(single==null){System.out.println("-----------------------");single=new Single();}} //{}中的代码就是排队执行的代码return single;}
synchronized 可以锁类,可以锁this,可以锁资源
当锁类的时候,相当于把这个类的所有对象整个锁住了
同步this,同步当前对象,锁住这个对象,这个对象的所有资源都被锁住了
如果只想要锁住其中某个资源,可以只锁这个资源,一般是成员变量
线程通信
* wait() 和 notify()通过操作同一份资源控制线程的通信,方法必须使用在同步的环境下
* wait()进入到对象(资源)的等待池中排队等待,等待被唤醒,会让出cpu的资源,同时也会释放对象的锁
* sleep() 让出cpu的资源,不会释放对象的锁
* notify() 唤醒正在等待的线程,只是具备了可执行的能力,就绪状态,如果想要执行,除了获取cpu的资源以外,还要拿到对象的锁
public class Demo01 extends Object{public static void main(String[] args) {Street street=new Street();new Thread(new Person(street)).start();new Thread(new Car(street)).start();}
}
class Street{//信号灯boolean flag=false;//we 东西 falsepublic void we(){if(flag==true){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}else{try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("车走...");flag=true;this.notify();}}//ns 南北 truepublic void ns(){if(flag==false){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}else{try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("人走...");flag=false;this.notify();}}
}
//人
class Person implements Runnable{Street street=null; //街道public Person(Street street) {super();this.street = street;}@Overridepublic void run() {synchronized (street) {while(true){street.ns();}}}
}
class Car implements Runnable{Street street=null; //街道public Car(Street street) {super();this.street = street;}@Overridepublic synchronized void run() {synchronized (street) {while(true){street.we();}}}
}
java重点基础:线程和同步锁和线程通信相关推荐
- 【JAVA SE】第十六章 进程、线程、同步锁和线程锁的简介
第十六章 进程.线程.同步锁和线程安全问题 文章目录 第十六章 进程.线程.同步锁和线程安全问题 一.进程 1.基本介绍 2.进程模型 二.线程 1.基本介绍 2.线程的生命周期 3.线程的优先级 4 ...
- 同步锁 php,python线程中同步锁详解
这篇文章主要为大家详细介绍了python线程中同步锁的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十 ...
- java 同步锁_java线程中的同步锁和互斥锁有什么区别?
在java中,同步锁和互斥锁英文关键字都是Synchronized,没有本质上的区别,两者都包括对资源的独占,使用起来没有区别.概念上的区别是 1:互斥是通过竞争对资源的独占使用,彼此没有什么关系,执 ...
- 线程及同步的性能 – 线程池/ ThreadPoolExecutors/ ForkJoinPool
线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自 ...
- Python 多线程、守护进程、同时运行最大线程数、锁、线程阻塞(线程暂停和继续)
python 多线程的使用笔记 1.多线程的基本用法 (1)简单任务多线程的开启方式 from threading import Thread import timedef target(name, ...
- Java并发基础:了解无锁CAS就从源码分析
CAS的全称为Compare And Swap,直译就是比较交换.是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在i ...
- Java并发基础:了解无锁CAS就从源码分析 1
CAS的全称为Compare And Swap,直译就是比较交换.是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在i ...
- java 同步解决不安全类_「JAVA」Java 线程不安全分析,同步锁和Lock机制,哪个解决方案更好...
线程不安全 线程不安全的问题分析:在小朋友抢气球的案例中模拟网络延迟来将问题暴露出来:示例代码如下: public class ImplementsDemo { public static void ...
- JAVA 基础(第二十六天)同步锁
目录 1 同步锁 1.1 前言 1.2 同步与异步 1.3 synchronized同步关键字 1.3.1 写法 1.3.2 前提 1.3.3 特点 1.4.1练习-改造售票案例 1.4.2 练习-改 ...
最新文章
- 【组合数学】递推方程 ( 递推方程示例 2 汉诺塔 | 递推方程示例 3 插入排序 )
- 服务器保存excel文件慢,从使用IE的服务器缓慢地保存Excel文件
- 适配器模式(为被封装对象提供不同的接口)
- mysql主从克隆服务器_mysql主从复制服务器配置
- java中非法运算符_Java 中的运算符和流程控制相关内容的理解
- SpringBoot2.0 整合 RocketMQ ,实现请求异步处理
- 修改数据_如何批量修改数据库中的特定记录数据
- 打开网页到我们看到页面显示的过程中发生了什么?
- 使用ajax请求cgi,Python CGI同步AJAX请求
- 欧姆龙NX系列PLC和工业软件的搜集资料
- PID算法 旋转倒立摆与平衡车的区别。此贴会更新。
- 通过 PPT 快速给证件照换底色
- 腾讯裁员范围扩大;研究称人类或能喝到月球冰火水;苹果考虑取消京东方3000万块屏幕订单;近视手术无法治愈近视
- NLP之分词技术理论
- Python爬虫获取网易云歌单封面(带Cookie)
- 用Python的statsmodels包做前向逐步回归
- TED-4-美好人生的定义
- Java 8 Update 201 (8u201)
- 基于微信小程序的面包店在线服务系统
- Ubuntu零基础教学-GParted磁盘分区工具使用|超级详细,手把手教学