方式一:继承thread 类
每个线程100张票
package com.example.starter;
public class SellTickets extends Thread{
public static void main(String[] args) {
Thread t1 = new SellTick1();
Thread t2 = new SellTick1();
Thread t3 = new SellTick1();
t1.start();
t2.start();
t3.start();
}
}
class SellTick1 extends Thread{
private int num = 100;
@Override
public void run(){
while(true){
if(num <= 0){
System.out.println("售票结束");
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口"+Thread.currentThread().getName()+ "售出 一张票 剩余票数=" + (--num ));
}
}
}
结果:
方式二:num 使用static修饰
一共100张票 有重复减票的情况,最后还有减成负数的情况
package com.example.starter;
public class SellTickets extends Thread{
public static void main(String[] args) {
Thread t1 = new SellTick1();
Thread t2 = new SellTick1();
Thread t3 = new SellTick1();
t1.start();
t2.start();
t3.start();
}
}
class SellTick1 extends Thread{
private static int num = 100;
@Override
public void run(){
while(true){
if(num <= 0){
System.out.println("售票结束");
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口"+Thread.currentThread().getName()+ "售出 一张票 剩余票数=" + (--num));
}
}
}
结果:
方式三:实现runnable的方式
package com.example.starter;
public class SellTickets extends Thread{
public static void main(String[] args) {
SellTicket2 sellTicket2 = new SellTicket2();
Thread t1 = new Thread(sellTicket2);
Thread t2 = new Thread(sellTicket2);
Thread t3 = new Thread(sellTicket2);
t1.start();
t2.start();
t3.start();
}
}
class SellTicket2 implements Runnable{
private int num = 100;
@Override
public void run() {
while(true){
if(num <= 0){
System.out.println("售票结束");
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
num --;
System.out.println("窗口"+Thread.currentThread().getName()+ "售出 一张票 剩余票数=" + (num));
}
}
}
结果
方式四:以上三种方式多存在多售票的问题,使用synchronized优化
package com.example.starter;
public class SellTickets extends Thread{
public static void main(String[] args) {
SellTicket2 sellTicket2 = new SellTicket2();
Thread t1 = new Thread(sellTicket2);
Thread t2 = new Thread(sellTicket2);
Thread t3 = new Thread(sellTicket2);
t1.start();
t2.start();
t3.start();
}
}
class SellTicket2 implements Runnable{
private volatile int num = 100;
private volatile boolean loop = true;
@Override
public void run() {
while(loop){
sell();
}
}
synchronized void sell(){
if(num <= 0){
System.out.println("售票结束");
loop = false;
return;
}
num --;
System.out.println("窗口"+Thread.currentThread().getName()+ "售出 一张票 剩余票数=" + (num));
}
}
结果:
方式五:
package com.example.starter;
public class SynSellTickets extends Thread{
public static void main(String[] args) {
SellTicket3 sellTicket3 = new SellTicket3();
Thread t1 = new Thread(sellTicket3);
Thread t2 = new Thread(sellTicket3);
Thread t3 = new Thread(sellTicket3);
t1.start();
t2.start();
t3.start();
}
}
class SellTicket3 implements Runnable{
private int num = 100;
private boolean loop = true;
@Override
public void run() {
while(loop){
synchronized (this){
if(num > 0){
num --;
System.out.println("窗口"+Thread.currentThread().getName()+ "售出 一张票 剩余票数=" + (num));
}else{
loop = false;
}
}
}
System.out.println("售票结束");
}
}
结果:
方式六:使用Lock类
class Resource{
private int num = 100;
Lock lock = new ReentrantLock();
boolean loop = true;
public void desStock(){
while(loop){
lock.lock();
try {
if(num > 0){
num --;
System.out.println("窗口"+Thread.currentThread().getName()+ "售出 一张票 剩余票数=" + (num));
}else{
loop = false;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
public class LockSellTickets extends Thread{
public static void main(String[] args) {
Resource resource = new Resource();
new Thread(()->{
resource.desStock();
},"AA").start();
new Thread(()->{
resource.desStock();
},"BB").start();
}
}
打印结果
方式七 atomic加syn
class Resource1{
private AtomicInteger at = new AtomicInteger(100);
boolean loop = true;
public int decStock(){
return at.decrementAndGet();
}
public void sell(){
while(loop){
synchronized (this){
int i = decStock();
if(i > 0){
System.out.println("窗口"+Thread.currentThread().getName()+ "售出 一张票 剩余票数=" + (i));
}else{
loop = false;
}
}
}
}
}
public class AtomicSellTickets extends Thread{
public static void main(String[] args) {
Resource1 resource = new Resource1();
new Thread(()->{
resource.sell();
},"AA").start();
new Thread(()->{
resource.sell();
},"BB").start();
}
}