java多线程售票小例子
1、错误示范
class SellThread implements Runnable {
private int i = 20;
public void run() {
while(true) {
if(i > 0) {
try {
Thread.sleep(100);
} catch(Exception e) {
}
System.out.println(Thread.currentThread().getName() + "sell " + i--);
}
}
}
}
public class Test {
public static void main(String[] args) {
SellThread sell = new SellThread();
Thread sell1 = new Thread(sell, "sellman1");
Thread sell2 = new Thread(sell, "sellman2");
Thread sell3 = new Thread(sell, "sellman3");
sell1.start();
sell2.start();
sell3.start();
}
}
没有同步控制变量,所以最后出现了-1张票
2、正确示范
class SellThread implements Runnable {
private int i = 20;
String key = "";
public void run() {
while(true) {
synchronized(key) {
if(i > 0) {
try {
Thread.sleep(100);
} catch(Exception e) {
}
System.out.println(Thread.currentThread().getName() + "sell " + i--);
}else {
break;
}
}
}
}
}
public class Test {
public static void main(String[] args) {
SellThread sell = new SellThread();
Thread sell1 = new Thread(sell, "sellman1");
Thread sell2 = new Thread(sell, "sellman2");
Thread sell3 = new Thread(sell, "sellman3");
sell1.start();
sell2.start();
sell3.start();
}
}
补充:如果用synchronized关键字修饰方法,则只能有一个线程获取访问这段方法的权限。也就是说,一个线程把票买完了才结束。
class SellThread implements Runnable {
private int i = 20;
String key = "";
public synchronized void run() {
while(true) {
if(i > 0) {
try {
Thread.sleep(100);
} catch(Exception e) {
}
System.out.println(Thread.currentThread().getName() + "sell " + i--);
}else {
break;
}
}
}
}
public class Test {
public static void main(String[] args) {
SellThread sell = new SellThread();
Thread sell1 = new Thread(sell, "sellman1");
Thread sell2 = new Thread(sell, "sellman2");
Thread sell3 = new Thread(sell, "sellman3");
sell1.start();
sell2.start();
sell3.start();
}
}
总结:
1、synchronized()括号中需要的是一个对象,所以这里使用了String类的一个对象key,可以用this来代替key。
2、一个线程拿到synchronized括号中的对象以后,其他线程也是可以执行的,但是当它们需要用key的时候,发现key已经被别人拿走了,只能等着key被释放了。就像上厕所,坑被别人占了,只能等着了,但是等着的时候我还可以运行,比如玩玩手机什么的。
3、synchronized method(){} 可以防止多个线程同时访问这个对象的synchronized方法;如果一个对象A,有多个synchronized方法,只要一个线程访问了其中的一个,那么其他线程不能同时访问A的任何一个synchronized方法。但是可以访问对象B的synchronized方法。
4、synchronized static method(){} 可以防止多个线程同时访问这个类的synchronized方法;对类的所有对象均起作用,无论对象A、对象B、对象C的。