java 多线程问题 卖车票
方法一:
如果创建一个类继承Thread线程则只能这样写
package lesson;
public class ThreadDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Ticket1 t1 = new Ticket1();
Ticket1 t2 = new Ticket1();
Ticket1 t3 = new Ticket1();
Ticket1 t4 = new Ticket1();
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t4.setName("窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Ticket1 extends Thread{
static int ticket = 1 ;
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (Ticket1.class) {
if (ticket > 100) {
System.out.println("票已经卖完了....");
break;
}else {
System.out.println(Thread.currentThread().getName() + "正在卖第" + (ticket++) + "张票");
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
这种方法只可在如上代码地方加字节码锁,即Ticket1.class
synchronized (Ticket1.class) {
}
把字节码改为this , 或者在run方法前面加锁都会出现错误
方法二:
如果继承Runnable接口
可以有三种写法
package lesson;
public class Demo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t4.setName("窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Ticket implements Runnable{
static int ticket = 1 ;
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (Ticket.class) {
if (ticket > 100) {
System.out.println("票已经卖完了....");
break;
}else {
System.out.println(Thread.currentThread().getName() + "正在卖第" + (ticket++) + "张票");
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
此处加的锁可以为
synchronized (this) {
}
或者
public synchronized void run() {
}
这三种方法都可对继承Runnable的线程加锁,并使车票成功卖出
总结
对于非静态方法,同一个实例的线程访问会被拦截,非同一实例可以同时访问。 即此时是默认对象锁(this)。
只要采用类锁,就会拦截所有线程,只能让一个线程访问。
对于对象锁(this),如果是同一个实例,就会按顺序访问,但是如果是不同实例,就可以同时访问。
如果对象锁跟访问的对象没有关系,那么就会都同时访问。