在之前售票系统(负票)版中,不管是用实现接口还是继承都有问题。
根本原因就是多个线程同时执行一个run()方法。
本次代码进行了改进,增加了synchronized。问题得到解决,详情看代码
实现互斥锁的步骤:
1.分析需要上锁的代码
2.选择同步代码块(建议使用,范围小,效率高)或同步方法
3.要求多个同步线程的锁对象为一个即可
tips:
同步方法(静态的)的锁为当前类本身
同步方法(非静态)的锁可以是this(注意区分new出来的对象是否为同一this),也可以是其他对象(要求是同一对象)
①synchronized加在方法上
package thread_;
public class TicketSystem {
public static void main(String[] args) {
TicketSystem02 ticketSystem02 = new TicketSystem02();
new Thread(ticketSystem02).start();//第一个线程
new Thread(ticketSystem02).start();//第二个线程
new Thread(ticketSystem02).start();//第三个线程
}
}
class TicketSystem02 implements Runnable{
private int ticketnum =100;//多个线程共享
private Boolean loop = true;
public void setLoop(Boolean loop) {
this.loop = loop;
}
public synchronized void sell(){//同步方法,在同一时刻,只有一个线程执行sell()方法
if (ticketnum<=0 ){//无票提示售罄
System.out.println("售罄");
setLoop(false);//执行到此会退出while循环
return;
}
try {
Thread.sleep(50);//有票间隔售卖时间 50ms
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口:"+Thread.currentThread().getName()+"售出一张票\t"+"还剩:"+(--ticketnum));
}
@Override
public void run() {//倘若在次写synchronized,则从头到尾只会由一个进程在售卖
while(loop){
sell();
}
}
}
②synchronized代码块 在非静态方法中
package thread_;
public class TicketSystem {
public static void main(String[] args) {
TicketSystem02 ticketSystem02 = new TicketSystem02();
new Thread(ticketSystem02).start();//第一个线程
new Thread(ticketSystem02).start();//第二个线程
new Thread(ticketSystem02).start();//第三个线程
}
}
class TicketSystem02 implements Runnable{
private int ticketnum =100;//多个线程共享
private Boolean loop = true;
Object object = new Object();
public void setLoop(Boolean loop) {
this.loop = loop;
}
public void sell(){
synchronized(object/*this*/){//不仅可以用this,只要是同一对象即可
if (ticketnum<=0 ){//无票提示售罄
System.out.println("售罄");
setLoop(false);
return;
}
try {
Thread.sleep(50);//有票间隔售卖时间 50ms
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口:"+Thread.currentThread().getName()+"售出一张票\t"+"还剩:"+(--ticketnum));
}
}
@Override
public void run() {//synchronized 同步方法,在同一时刻,只有一个线程才能执行run()方法
while(loop){
sell();
}
}
}
③synchronized代码块 在静态方法中(代码有错误,只提供参考)
package thread_;
public class TicketSystem {
public static void main(String[] args) {
TicketSystem02 ticketSystem02 = new TicketSystem02();
new Thread(ticketSystem02).start();//第一个线程
new Thread(ticketSystem02).start();//第二个线程
new Thread(ticketSystem02).start();//第三个线程
}
}
class TicketSystem02 implements Runnable{
private int ticketnum =100;//多个线程共享
private Boolean loop = true;
Object object = new Object();
public void setLoop(Boolean loop) {
this.loop = loop;
}
public static void sell(){
synchronized(TicketSystem02.class){//此时要用类名,因为互斥锁是加在类上的
if (ticketnum<=0 ){//无票提示售罄
System.out.println("售罄");
setLoop(false);
return;
}
try {
Thread.sleep(50);//有票间隔售卖时间 50ms
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口:"+Thread.currentThread().getName()+"售出一张票\t"+"还剩:"+(--ticketnum));
}
}
@Override
public void run() {//synchronized 同步方法,在同一时刻,只有一个线程才能执行run()方法
while(loop){
sell();
}
}
}