package xiancheng;
/*
定义一个MaiPiao类实现Runnable接口,里面定义一个成员变量: private int tickets =100(票数);
在类中重写run()方法实现卖票,代码步骤如下
1:判断票数大于0,就卖票,并告知是哪个窗口卖的
2:卖了票之后,总票数要减1
3:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
定义一个测试类MaiPiaoDemo,里面有main方法,代码步骤如下
1:创建MaiPiao类的对象
2:创建三个Thread类的对象,把MaiPiao对象作为构造方法的参数,并给出对应的窗口名称
3:启动线程
*/
public class MaiPiaoDome {
public static void main(String[] args) {
//创建MaiPiao类的对象
MaiPiao m=new MaiPiao();
//创建三个Thread类的对象,把MaiPiao对象作为构造方法的参数,并给出对应的窗口名称
Thread t1=new Thread(m,"售票口1");
Thread t2=new Thread(m,"售票口2");
Thread t3=new Thread(m,"售票口3");
//启动线程
t1.start();
t2.start();
t3.start();
}
}
package xiancheng;
public class MaiPiao implements Runnable {
private int tickets =100;
public void run() {
while(true) {
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
同步代码块学习记录:
在MaiPiao类中添加了sleep()方法后
出现了问题 如出现卖的票数为-1或者同个窗口卖出一样的票
为什么出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)
1、是否是多线程环境
2、是否有共享数据
3、是否有多条语句操作共享数据
如何解决多线程安全问题呢?
基本思想:让程序没有安全问题的环境
怎么实现呢?
把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可Java提供了同步代码块的方式来解决
锁多条语句操作共享数据,可以使用同步代码块实现
格式:
synchronized(任意对象){
多条语句操作共享数据的代码
}
synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
使用同步代码块后的MaiPiao类:
package xiancheng;
public class MaiPiao implements Runnable {
private int tickets =100;
private Object obj =new Object();
public void run() {
while(true) {
synchronized(obj) {
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
}
同步方法学习记录:
package xiancheng;
/*
同步方法:就是把synchronized关键字加到方法上
格式:
修饰符synchronized返回值类型 方法名(方法参数){}
同步方法的锁对象是什么呢?
this
同步静态方法:就是把synchronized关键字加到静态方法上
格式:
修饰符static synchronized返回值类型 方法名(方法参数){}
同步静态方法的锁对象是什么呢?
类名.class
*/
public class MaiPiao implements Runnable {
//private int tickets =100;
private static int tickets =100;
private Object obj =new Object();
private int x=0;
public void run() {
while(true) {
if(x%2==0) {
//synchronized(obj) {
//同步方法的锁对象是什么呢? this
// synchronized(this) {
// 同步静态方法的锁对象是什么呢?
// 类名.class
synchronized(MaiPiao.class) {
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
else {
// synchronized(obj) {
// if(tickets>0) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
// tickets--;
// }
// }
s();
}
x++;
}
}
//同步方法:就是把synchronized关键字加到方法上
// 格式:
// 修饰符synchronized返回值类型 方法名(方法参数){}
// public synchronized void s() {
// if(tickets>0) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
// tickets--;
// }
// }
// 同步静态方法:就是把synchronized关键字加到静态方法上
// 格式:
// 修饰符static synchronized返回值类型 方法名(方法参数){}
public static synchronized void s() {
if(tickets>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}