一,基础概念部分
可以在菜鸟教程或者w3cschool上了解到
一,购票问题
package test_5;
public class Ticket implements Runnable{
private int tickets=20;
@Override
public void run() {
while(tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
tickets--;
System.out.println("【"+Thread.currentThread().getName()+"】售出一张票,还剩【"+tickets+"】张");
}
}
}
运行结果:
通过观察发现,出现了线程安全问题
解决方案:
1,使用synchronized (){}或public synchronized void run(){}
2,使用lock锁
3,使用阻塞队列BlockingQueue
synchronized (){}方法:
package test_5;
public class Ticket implements Runnable{
private int tickets=20;
@Override
public void run() {
while (true){
synchronized (this){//this为当前方法对象
if(tickets>0){
tickets--;
System.out.println(Thread.currentThread().getName()+"售票,还有"+tickets);
}
else{
System.out.println("票已售完!!!");
break;
}
}
}
}
}
注:synchronized 同步锁中的对象必须为同一个
运行结果:
public synchronized void run(){}方法:
package test_5;
public class Ticket implements Runnable{
private int tickets=20;
@Override
public void run() {
for(int i=0;i<10;i++){
sell();
}
}
public synchronized void sell(){
if(tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
tickets--;
System.out.println(Thread.currentThread().getName()+"售票,还有"+tickets);
}
else{
System.out.println("票已售完!!!");
}
}
}
运行结果:
注:不能先加锁再循环
使用lock锁:
package test_5;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Ticket implements Runnable{
private int tickets=20;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true){
lock.lock();
if(tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
tickets--;
System.out.println(Thread.currentThread().getName()+"售票,还有"+tickets);
}
else{
System.out.println("票已售完!!!");
break;
}
lock.unlock();
}
}
}
运行结果:
使用阻塞队列BlockingQueue:
package test_4;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Ticket implements Runnable{
private static BlockingQueue queue =new LinkedBlockingQueue();
static { //初始化queue
for(int i=0;i<100;i++){
queue.add(i);
}
}
@Override
public void run() {
while(queue.size()>0){
if(queue.size()>0){
queue.poll();
System.out.println(Thread.currentThread().getName()+"售票,还有"+queue.size());
}
else {
break;
}
}
}
}
