package com.bupt.exer;
/**
* 列子:创建三个窗口卖票,总票数为100张,使用实现的runnable接口方式
* 1. 问题:买票过程中出现重票和错票
* 2.原因:当某个线程操作过程中,另一个线程也参与进来
* 3.解决方式:当一个线程a在操作ticket的时候,其他线程不能参与进来,
* 直到线程a操作完ticket时,其他线程才可以开始操作ticket,这种情况即使线程a
* 出现了阻塞,也不能被改变。
*
* 4. 在java中,我们通过同步机制,来解决线程安全问题
* 方式一: 同步代码块
* synchroized(同步监视器){
* //需要被同步的代码
* }
*说明:1、操作共享数据的代码,即为需要被同步的代码
* 2、共享数据:多个线程共同操作的代码,比如ticket
* 3、同步监视器,俗称锁,任何一个类的对象都可以称为锁。
* 要求:多个线程必须共用同一把锁
* 4、在继承Thread类中创建多线程方式中,慎用this充当同步显示器
* 可以考虑当前类来充当同步监视器
* 5、在实现Runnable接口创建多线程的方式中,我们可以考虑使用
* this充当同步监视器
* 方法二:同步方法
*
*5. 同步的方式解决了线程的安全问题----好处
* 操作同步代码时,只能有一个线程参与,其他线程等待,相当于一个单线程,效率低----局限性
*
*
*
*/
class ticketWindows1 implements Runnable{
private int ticket = 100;
Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) { //或者用this 当前对象
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ": " + ticket);
ticket--;
} else {
break;
}
}
}
}
}
public class windows1 {
public static void main(String[] args) {
ticketWindows1 ticketWindows = new ticketWindows1();
Thread t1 = new Thread(ticketWindows);
Thread t2 = new Thread(ticketWindows);
Thread t3 = new Thread(ticketWindows);
t1.setName("a");
t2.setName("b");
t3.setName("c");
t1.start();
t2.start();
t3.start();
}
}
package com.bupt.exer;
//使用继承Thread的方式来卖票
class ticketWindows extends Thread{
private static int ticket = 100;
private static Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) { //用ticketWindows.class,类也是对象,只会加载一次
if (ticket > 0) {
System.out.println(getName() + ": " + ticket);
ticket--;
} else {
break;
}
}
}
}
}
public class windows {
public static void main(String[] args) {
Thread t1 = new ticketWindows();
t1.setName("t1");
Thread t2 = new ticketWindows();
t2.setName("t2");
Thread t3 = new ticketWindows();
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}