导师教我们用Java做面向对象式魔方,原来Java还能这么玩!

@Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } } 了解更多Java知识,获取原视频,源码,学习交流,那就加入小编的学习交流群吧!616 959 444 以上一堆代码就是一个创建子类重写父类方法的过程 相当于: new MyThread().start(); 程序出现了线程安全问题:卖了重复的票和不存在的票 解决方案: 第一种方式:可以使用同步代码块 synchronized(锁对象){ 产生安全问题的代码; 访问了共享数据的代码; } 注意: 必须要保证多个线程使用的是同一个锁对象 //在成员位置上创建一个锁对象(保证唯一) Object obj = new Object(); @Override public void run() { //让卖票重复执行 while(true){ * 同步代码块 * 程序会频繁的判断锁,获取锁,释放锁,所以会降低速度 synchronized (obj) { if(ticket>0){ //为了提高安全问题的概率,让程序睡眠 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //卖票ticket-- System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票"); } } } } 了解更多Java知识,获取原视频,源码,学习交流,那就加入小编的学习交流群吧!616 959 444 程序出现了线程安全问题:卖了重复的票和不存在的票 解决方案: 第二种方式:同步方法 使用步骤: 1.把可能出现安全问题的代码抽取到一个方法中 2.把方法增加一个关键字synchronized 修饰符 synchronized 返回值类型 方法名(参数){ 可能出现安全问题的代码; 访问了共享数据的代码; } 同步方法使用的锁对象是什么? 使用的就是本类对象new RunnableImpl()-->叫this 静态的同步方法,使用时什么锁对象? 使用的是本类对象的class属性(反射) RunnableImpl.class * @Override public void run() { //让卖票重复执行 while(true){ payTicket2(); } } * 静态的同步方法 public static synchronized void payTicket2(){ synchronized (RunnableImpl.class) { if(ticket>0){ //为了提高安全问题的概率,让程序睡眠 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //卖票ticket-- System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票"); } } } * 抽取出一个同步方法 * 快捷键:alt+shift+m public ynchronized void payTicket1() { synchronized (this) { //System.out.println(this);//cn.itcsat.demo10.RunnableImpl@67064 if(ticket>0){ //为了提高安全问题的概率,让程序睡眠 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //卖票ticket-- System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票"); } } } 程序出现了线程安全问题:卖了重复的票和不存在的票 * * 解决方案: * 第三种方式:使用Lock接口,JDK1.5之后出现的 * * java.util.concurrent.locks.Lock接口 * 方法: * void lock() 获取锁。 * void unlock() 释放锁。 * 接口的实现类:ReentrantLock * * 实现步骤: * 1.在成员位置创建一个Lock接口的实现类对象ReentrantLock * 2.在可能出现线程安全问题的代码前,调用lock方法获取锁 * 3.在可能出现线程安全问题的代码后,调用unlock方法释放锁 * *1.在成员位置创建一个Lock接口的实现类对象ReentrantLock 了解更多Java知识,获取原视频,源码,学习交流,那就加入小编的学习交流群吧!616 959 444 Lock l = new ReentrantLock(); @Override public void run() { //让卖票重复执行 while(true){ //2.在可能出现线程安全问题的代码前,调用lock方法获取锁 l.lock(); if(ticket>0){ //为了提高安全问题的概率,让程序睡眠 try { Thread.sleep(10); //卖票ticket-- System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票"); } catch (InterruptedException e) { e.printStackTrace(); }finally { //3.在可能出现线程安全问题的代码后,调用unlock方法释放锁 l.unlock(); } } } 记住:永远别放弃你当初踏入社会时的梦想,那是你现在最美好的梦想啊!

转载于:https://my.oschina.net/u/3551068/blog/1002651

你可能感兴趣的:(导师教我们用Java做面向对象式魔方,原来Java还能这么玩!)