网页设计和网站开发的区别,网站建设中服务器的搭建方式,品牌网站设计图片,网站建设开发的目的目录#xff1a;
线程安全线程同步同步代码块同步方法Lock锁线程状态图sleep睡眠等待和唤醒
1. 线程安全
如果有多个线程在同时运行#xff0c;而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样 的#xff0c;而且其他的变量的值也和预期的是…目录
线程安全线程同步同步代码块同步方法Lock锁线程状态图sleep睡眠等待和唤醒
1. 线程安全
如果有多个线程在同时运行而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样 的而且其他的变量的值也和预期的是一样的就是线程安全的。
我们通过一个案例演示线程的安全问题 电影院要卖票我们模拟电影院的卖票过程。假设要播放的电影是 “葫芦娃大战奥特曼”本次电影的座位共100个(本 场电影只能卖100张票)。我们来模拟电影院的售票窗口实现多个窗口同时卖 “葫芦娃大战奥特曼”这场电影票(多个窗口一起卖这100张票) 需要窗口采用线程对象来模拟需要票Runnable接口子类来模拟 模拟票
public class Ticket implements Runnable {
private int ticket 100;
/*
* 执行卖票操作
* */
Override
public void run() {
//每个窗口卖票的操作
//窗口 永远开启
while (true) {
if (ticket 0) {//有票 可以卖
//出票操作
//使用sleep模拟一下出票时间
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获取当前线程对象的名字
String name Thread.currentThread().getName();
System.out.println(name 正在卖: ticket--);
}
}
}
}测试类
public class Demo {
public static void main(String[] args) {
//创建线程任务对象
Ticket ticket new Ticket();
//创建三个窗口对象
Thread t1 new Thread(ticket, 窗口1);
Thread t2 new Thread(ticket, 窗口2);
Thread t3 new Thread(ticket, 窗口3);
//同时卖票
t1.start();
t2.start();
t3.start();
}
}效果图 相同的票数,比如5这张票被卖了3回。不存在的票比如0票与-1票是不存在的。 这种问题几个窗口(线程)票数不同步了这种问题称为线程不安全。 2. 线程同步
线程同步是为了解决线程安全问题。 Java中提供了同步机制(synchronized)来解决。 根据案例简述 窗口1线程进入操作的时候窗口2和窗口3线程只能在外等着窗口1操作结束窗口1和窗口2和窗口3才有机会进入代码去执行。也就是说在某个线程修改共享资源的时候其他线程不能修改该资源等待修改完毕同步之后才能去抢夺CPU资源完成对应的操作保证了数据的同步性解决了线程不安全的现象。 有三种方式完成同步操作 同步代码块。同步方法。锁机制。 3.同步代码块
同步代码块 synchronized 关键字可以用于方法中的某个区块中表示只对这个区块的资源实行互斥访问。 格式:
synchronized(同步锁){
需要同步操作的代码
}对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁 锁对象 可以是任意类型。多个线程对象 要使用同一把锁。 代码演示
public class Ticket implements Runnable {private int ticket 100;Object lock new Object();
// 执行卖票操作Overridepublic void run() {
//每个窗口卖票的操作
//窗口 永远开启while (true) {synchronized (lock) {if (ticket 0) {//有票 可以卖
//出票操作
//使用sleep模拟一下出票时间try {Thread.sleep(50);} catch (InterruptedException e) {
// TODO Auto-generated catch blocke.printStackTrace();}
//获取当前线程对象的名字String name Thread.currentThread().getName();System.out.println(name 正在卖: ticket--);}}}}
}4.同步方法
同步方法:使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着 格式
public synchronized void method(){
可能会产生线程安全问题的代码
}同步锁是谁? 对于非static方法,同步锁就是this。对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。 使用同步方法代码如下
public class Ticket implements Runnable{private int ticket 100;/** 执行卖票操作*/Overridepublic void run() {
//每个窗口卖票的操作
//窗口 永远开启while(true){sellTicket();}}/** 锁对象 是 谁调用这个方法 就是谁* 隐含 锁对象 就是 this**/public synchronized void sellTicket(){if(ticket0){//有票 可以卖
//出票操作
//使用sleep模拟一下出票时间try {Thread.sleep(100);} catch (InterruptedException e) {
// TODO Auto-generated catch blocke.printStackTrace();}
//获取当前线程对象的名字String name Thread.currentThread().getName();System.out.println(name正在卖:ticket--);}}
}5.Lock锁
Lock介绍: Lock更加灵活,它里面有相应的方法 public void lock() :加同步锁。public void unlock() :释放同步锁。 Lock实现类: ReentrantLock Lock使用标准方式 l.lock(); 获得锁try {操作共享资源的代码} finally {l.unlock();}public class SaleTicketRunnable implements Runnable {int ticketNum 100; // 表示100张票Lock l new ReentrantLock();Overridepublic void run() {// 2.重写run方法,在run方法中实现这个卖票逻辑String name Thread.currentThread().getName();while (true) {// 如果票数大于0,就卖一张l.lock(); // 获得锁try {if (ticketNum 0) {try { // 模拟卖票要花的时间Thread.sleep(10);} catch (InterruptedException e) {}ticketNum--;System.out.println(name 卖了一张票,剩余: ticketNum);} else {// 没有票了,结束循环,停止了卖票break;}} finally {l.unlock(); // 释放锁}}}
}6. 线程状态
线程状态图
7. 睡眠sleep方法 public static void sleep(long time) 让当前线程进入到睡眠状态到毫秒后自动醒来继续执行 public class Test{
public static void main(String[] args){
for(int i 1;i5;i){
Thread.sleep(1000);//主线程执行到sleep方法会休眠1秒后再继续执行。
System.out.println(i)}}
}8. 等待和唤醒
讲解 public void wait() : 让当前线程进入到等待状态 此方法必须锁对象调用.等待和唤醒,通常是两个线程之间的事情,一个线程等待,另外一个线程负责唤醒 Object类的方法: void wait() 导致当前线程等待void notify() 唤醒正在等待的单个线程 注意: wait和notify必须在同步代码块中,使用锁对象来调用
两道面试题
1.为什么wait和notify方法放在Object wait和notify使用锁对象来调用,任何对象都可以作为锁,所以就放在Object类中 2.sleep和wait的区别 1.sleep睡眠的时候不会释放锁 2.wait等待的时候会释放锁 public static void main(String[] args) throws InterruptedException {Object obj new Object();// obj.wait(); // IllegalMonitorStateException: 非法监视状态异常new Thread(new Runnable() {Overridepublic void run() {synchronized (obj) {try {System.out.println(wait前);obj.wait();System.out.println(wait后);} catch (InterruptedException e) {}}}}).start();Thread.sleep(3000);new Thread(new Runnable() {Overridepublic void run() {synchronized (obj) {System.out.println(准备唤醒);obj.notify();}}}).start();}