Java实现多线程售票

Synchronized和Lock的区别是什么?

1.synchronized是Java中的关键字,是jdk自带的;Lock是一个接口
2.synchronized在线程执行发生异常时,jvm会让线程释放锁,因此不会导致死锁现象发生;Lock在finally中必须通过unLock()去释放锁,不然容易造成线程死锁
3.使用synchronized时,如果A线程阻塞,B线程会一直等待,不能够响应中断;Lock可以尝试获得锁,线程可以不用一直等待,通过interrupt()方法能够响应中断(interrupt无法中断已经获取的锁,只能中断等待状态)
4.synchronized无法判断锁的状态;Lock可以知道有没有成功获取锁(可以通过其中的tryLock()等自带的多个方法去尝试获取锁)

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当多线程竞争资源非常激烈时,此时Lock的性能要远远优于synchronized。具体使用时要根据适当情况选择。

案例一

方法一 继承Thread类

package sell;

import java.lang.Thread;

public class SaleSysTest {

	public static void main(String[] args) {
		
		//创建5个线程,传入线程名[001]、[002]...并开启
		for(int i=1;i<6;i++) {
			new SaleThread("[00"+i+"]").start();
		}
	}

}

class SaleThread extends Thread{
	
	//车票数被共享,所以定义为static,数量为50.
	private static int ticket=50;
	//通过锁来保证线程不会重复访问
	private static Object obj=new Object();
	
	//有参构造传入线程名
	public SaleThread(String name) {
		// TODO Auto-generated constructor stub
		super(name);
	}
	//无参构造传入线程名
	public SaleThread() {
		
	}
	
	//重写run()方法,将售票动作放入其中
	public void run() {
		while(true) {
			//在锁外使用sleep(),以便于更好的解决复现问题
			try {
					Thread.sleep(100);
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
			//使用synchronized需要锁统一资源,不然没效果,所以将obj初始化为static静态。
			//但让也可以使用字符串 synchronized("lock");lock随便输入
			synchronized(obj) {
				//还有余票---出票
				if(ticket>0) {
					System.out.println(Thread.currentThread().getName()+"号窗口第"+ticket+"票 正在出票...");
					ticket--;
				}else {
					//车票售罄
					System.out.println("车票已售罄,下次请趁早...");
					//退出
					System.exit(0);
				}
			}
		}
	}
}

方法二 实现Runnable接口

package sell;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

class Selldemolist implements Runnable {
	Scanner in=new Scanner(System.in);
    int tickets=in.nextInt();
    private int salenum=0;
    
    public void sellTickets() {	
        synchronized (this) {
            if (tickets > 0) {
            tickets--;
            salenum++;
            System.out.println(Thread.currentThread().getName() + "已经购买编号为"+salenum+"的票");
            Date date=new Date();
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String time=sdf.format(date);
            System.out.println("出票时间为:"+time);
            try {
            	Thread.sleep(500);
			} catch (InterruptedException e) {	
				e.printStackTrace();
			}
            System.out.println("___________________________________");
            System.out.println("                                     ");
            }
        }
    }
 public void run() {
        while (tickets > 0) {
            sellTickets();
            try {
               
                Thread.sleep(400);
                if(tickets==0){
                System.out.println("非常抱歉,售票已经结束,请明天再来!");
                 System.exit(-1);
                
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
        }
    }
    
}

public  class  Selldemo1 {
	public static void main(String[] args) {
		Selldemolist ticket=new Selldemolist();
		Thread mary = new Thread(ticket,"玛丽");
		Thread jack = new Thread(ticket,"杰克");
		Thread rose=new Thread(ticket,"柔丝");
		Thread black=new Thread(ticket,"布莱克");
		mary.start();
		jack.start();
		rose.start();
		black.start();
	}
}

案例二

方法一 继承Thread类

package Demo;

public class Sellticket1 {
	public static void main(String[] args) {
		
		//创建3个线程,并开启
		for(int i=1;i<4;i++){
			new TicketWindow("窗口"+i+":").start();
		}
		
	}
}

  //方法1.继承Thread类
class TicketWindow extends Thread{

	private static int ticket = 100;//车票数被共享,所以定义为static	
	private static Object obj = new Object();//通过锁来保证线程不会重复访问
	
	//有参构造传入线程名
	public TicketWindow(String name) {
		super(name);
	}
	
	public TicketWindow() {
		
	}

	//重写run()方法,将售票动作放入其中
	public void run() {
		while (true) {
			//在锁外使用sleep( );以便于更好的解决复现问题
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			//也可以使用字符串 synchronized("lock");lock随便输入
			synchronized (obj) {			
				if (ticket > 0) {
					System.out.println(Thread.currentThread().getName() + "第-- "+ ticket + " --票正在出票...");
					ticket--;
				} else {					
					System.out.println("票已售完   下次再见!!");
					System.exit(0);
				}
			}
		}
	}	
}

方法二 实现Runnable接口

package Demo;

public class Sellticket2 {
	public static void main(String[] args) {
		
		Windows sc = new Windows();
		//创建3个线程,并开启
		for(int i=1;i<4;i++){
			new Thread(sc,"窗口"+i).start();
		}

	}	
}

//方法2.实现Runnable接口
class Windows implements Runnable{
	
    private int ticket = 100;  
    private Object obj = new Object(); //定义一个线程同步对象
    
    public void run() {        
        while(true){
 			 try {
                Thread.sleep(50);
              } catch (InterruptedException e) {
                 e.printStackTrace();
              }
 			 
            //同步锁
            synchronized(obj){
                if(ticket > 0){
                    System.out.println(Thread.currentThread().getName()+" 售出第-- "+ticket +" --张票");
                    ticket--;
                }else{
                    System.out.println("票已售完   下次再见!!");
                    System.exit(0);
                }
            }
        }       
    }
}

案例三

方法一 继承Thread类

package xiancheng;

import java.util.Scanner;

class thread extends Thread {
	public static int num, num1;
	public static Object obj = new Object();
	public int i = 1;
	public thread(String name) {
		super(name);
	}
	public thread() {
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		while(true) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			synchronized(obj) {
				if(num > 0) {
					System.out.println("售票点:" + Thread.currentThread().getName() + "  当前卖出票号:" + (num1 - num + 1) );
					num--;
				} else {
					System.out.println("已卖完");
					System.exit(0);
				}
			}
		}
	}
	public void getChePiao(int chePiao) {
		num = chePiao; 
		num1 = chePiao;
	}
}

public class DoThread {
	
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int i;
		Scanner scanner = new Scanner(System.in);
		System.out.print("请问要卖多少张票:");
		new thread().getChePiao(scanner.nextInt());
		for(i = 1 ; i <= 4 ; i++) {
			new thread("" + i).start();
		}
	}

}

方法二 实现Runnable接口

package xiancheng;

import java.util.Scanner;

class Runn implements Runnable {
	public int num, i = 1, num1;
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		while(true) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			doRun();
			if(num <= 0) {
				System.exit(0);;
			}
		}
	}
	public synchronized void doRun() {
		if(i > 0 && i <= num1) {
			System.out.println("售票点:" + Thread.currentThread().getName() + "  当前卖出票号:" + i);
			i++;
			num--;
		} else if(num <= 0) {
			System.out.println("已卖完");
			System.exit(0);
		}
	}
	public void getChePiao() {
		Scanner scanner = new Scanner(System.in);
		System.out.print("请问要卖多少张票:");
		num = scanner.nextInt(); 
		num1 = num;
	}
}

public class DoRunnable {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int i;
		Runn runn = new Runn();
		runn.getChePiao();
		for(i = 1 ; i <= 4 ; i++) {
			new Thread(runn, "" + i).start();
		}
	}
}

案例四

方法一 继承Thread类

package one;

import java.util.Scanner;

public class Sale {
	private static int ticket,temp;
	public static void  main(String [] args) {
		
		System.out.println("请输入您发放的票数:");
		Scanner in = new Scanner(System.in);
		String x = in.nextLine();
		ticket = Integer.parseInt(x);
		temp = ticket; 
		for(int i=1;i<6;i++) {
			new sell1(" ["+i+"]",temp).start();
		}
	}
}

class sell1 extends Thread { 
	 private static int ticket,temp1;
	 private static Object obj = new Object();
	 
	 public sell1() {
		 
	 }
	 public sell1(String name,int temp) {
		 
		 super (name);
		 ticket = temp;
	 }
	 @Override
	 public void run() {
		 temp1 = ticket;
		 while (true) {
			 try {
				 Thread.sleep(100);
				 
			 }
			 catch(InterruptedException e) {
				 e.printStackTrace();
			 }
	
			 synchronized (obj) {
				 if(ticket>0) {
					 int a = temp1-ticket+1;
					 System.out.println("售票点:"+Thread.currentThread().getName()+ "\t当前票号:   "+a);
					 ticket--;
				 }
				 else {
					 System.out.println("车票已经售完,下次请趁早...");
					 System.exit(0);
				 }
			 }
		 }
	 }
}

方法二 实现Runnable接口

package two;

import java.util.Scanner;

public class Sale2 {
	public static void  main(String [] args) {
		int ticket1;
		System.out.println("请输入您发放的票数:");
		Scanner in = new Scanner(System.in);
		String x = in.nextLine();
		ticket1 = Integer.parseInt(x);
		sell s = new sell(ticket1); 
		for(int i=1;i<6;i++) {
			new Thread(s,"["+i+"]").start();
		}
	}
}

class sell implements Runnable{ 
	 private static int ticket,temp1;
	 private static Object obj = new Object();
	 
	 public sell() {
		 
	 }
	 public sell(int ticket1) {
		 ticket = ticket1;
	 }
	 @Override
	 public void run() {
		 temp1 = ticket; 
		 while (true) {
			 try {
				 Thread.sleep(100);
				 
			 }
			 catch(InterruptedException e) {
				 e.printStackTrace();
			 }
	
			 synchronized (obj) {
				 if(ticket>0) {
					 int a = temp1-ticket+1;
					 System.out.println("售票点:"+Thread.currentThread().getName()+ "\t当前票号:   "+a);
					 ticket--;
				 }
				 else {
					 System.out.println("车票已经售完,下次请趁早...");
					 System.exit(0);
				 }
			 }
		 }
	 }
}

案例五

方法一 继承Thread类

package eclipse;

public class Ticket1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//首先创建5个线程,传入线程名:如[001]、[002]等,并将其开启。
		int i;
		for(i=1;i<+5;i++) {
			new SaleThread("[00"+i+"]").start();
		}
	}

}
class SaleThread extends Thread{
	//由于车票数要对公众共享,所以要定义为静态成员变量,数量定为100.
	private static int ticket=100;
	//通过锁来保证线程都不会被重复访问.
	private static Object obj=new Object();
	//把有参构造传入线程名
	public SaleThread(String name) {
		super(name);
	}
	public SaleThread(){
		
	}

//重新写入run()方法,将售票动作放入其中;
@Override
public void run() {
	while(true) {
		//要在锁外使用sleep();	
try {
	Thread.sleep(100);
	
}catch(InterruptedException e) {
     e.printStackTrace();

	}
	//使用synchronized需要统一资源,不然没效果,所以将obj初始化为static静态.
	//但让也可以使用字符串 synchronized("lock");lock随便输入
synchronized(obj) {
	
	//还有余票——————出票
	if(ticket>0) {
		System.out.println(Thread.currentThread().getName()+"号窗口正在出票...票号:"+ticket);
		ticket--;
	}else {
		//利用if,else语句来看看车票售出的情况,如果售出完成,则执行else下面的语句。
		System.out.println("车票已经售完,下次请趁早买票!");
		System.exit(0);
	}
}
}
}
}	

方法二 实现Runnable接口

package eclipse;

public class Ticket2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//首先得到对象
		SaleSys a =new SaleSys();
		//然后把对象放入线程中
	for(int i=1;i<6;i++) {
		new Thread(a,"[00"+i+"]").start();
	}
	}

}

class SaleSys implements Runnable{
	//定义票的总数
	private int ticket = 100;
	//定义一个线程同步的对象
	private Object obj=new Object();
	
	@Override
	public void run() {
		while(true) {
			try {
				Thread.sleep(50);
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
			//同步锁
			synchronized(obj) {
				if(ticket>0) {
					System.out.println(Thread.currentThread().getName()+"号窗口正在售票...票号:"+ticket);
					ticket--;
				}else {
					System.out.println("票已售完,请下次再来吧!");
					System.exit(0);
		}
		}
		}
	}
}

案例六

方法一 继承Thread类

package com.hym.Threaded;

public class Sale_Thread{
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//创建五个窗口(线程)
		for(int i = 1;i < 6;i++) {
			new SaleThread("[0" + i + "]").start();
	}
	
	}
}
class SaleThread extends Thread{
	//车票数为共享变量,静态变量定义用static,数量为100
	private static int tickets = 100;
	//通过锁使这个线程不会被重复访问
	private static Object obj = new Object();
	public SaleThread(String name) {
		super(name);
	}
	public SaleThread() {
		
}

//重写run方法
@Override
public void run() {
	while(true) {
		try {
			Thread.sleep(200);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		//将obj初始化为static静态
		synchronized (obj) {
			if(tickets > 0) {
				System.out.println(Thread.currentThread().getName() + "号窗口第" + tickets-- + "票正在出票...");
			}
			else {
				//车票售完
				System.out.println("车票已售罄。");
				System.exit(0);
			}
		}
	}
}
	
}

方法二 实现Runnable接口

package com.hym.Threaded;

public class Test2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SaleSys s = new SaleSys();
		//创建五个窗口(线程)
		for(int i = 1;i < 6;i++) {
			new SaleThread("[0" + i + "]").start();
		}

	}

}
class SaleSys implements Runnable{
	//车票数为共享变量,静态变量定义用static,数量为100
	private static int tickets = 100;
	//通过锁使这个线程不会被重复访问
	private static Object obj = new Object();

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			try {
				Thread.sleep(200);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			//将obj初始化为static静态
			synchronized (obj) {
				if(tickets > 0) {
					System.out.println(Thread.currentThread().getName() + "号窗口第" + tickets-- + "票正在出票...");
				}
				else {
					//车票售完
					System.out.println("车票已售罄。");
					System.exit(0);
				}
			}
		
		}
	}
}

案例七

方法一 继承Thread类

package 售票;

public class duo2 {
	public static void main(String[] args) {
		for(int i=1; i<4; i++){
			chuangkou2 sp = new chuangkou2();
			sp.setName(i+"号窗口");
			sp.start();
		}
	}

}
class chuangkou2 extends Thread{
	private int tickets = 10;//车票总量
	
	public void run(){
		while(true){
			if(tickets>0){
				System.out.println(Thread.currentThread().getName() + "准备售票");                    
                tickets--;                                                                                              
                System.out.println(Thread.currentThread().getName() + "卖出一张,剩余票数:" + tickets + "张");
                try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			else{
				System.out.println(Thread.currentThread().getName() + "余票不足,停止售票!");
				break;
			}
		}
	}
}

方法二 实现Runnable接口

package 售票;

public class duo{
	public static void main(String[] args) {
	chuangkou sp = new chuangkou();
	for(int i=1; i<4; i++){
		Thread t = new Thread(sp, i +"号窗口");
		t.start();
	}
}

}
class chuangkou implements Runnable{
	private int tickets = 10;
	
	public void run(){
		while(true){
			if(tickets>0){
				shoupiao();
			}
			else{
				System.out.println(Thread.currentThread().getName() + "余票不足,停止售票!");
				break;
			}
		}
	}
	public synchronized void shoupiao(){
		if(tickets>0){
			System.out.println(Thread.currentThread().getName() + "准备售票");                    
            tickets--;                                                                                              
            System.out.println(Thread.currentThread().getName() + "卖出一张,剩余票数:" + tickets + "张");
            try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

案例八

方法一 继承Thread类

package Thread;


import java.util.Calendar;

import javax.xml.crypto.Data;

import java.util.*;
class sale_Thread extends Thread 
{
	private static volatile int tickets=2000;
	public synchronized void run()
	{
		while(tickets>0)
		{
			use();
		}
	}
	private synchronized static void use()
	{
			if(tickets>0)
			{
				System.out.println(Thread.currentThread().getName() +"售出第"+tickets--+"张票");
			}
//			try {
//				Thread.sleep(200);
//			} catch (InterruptedException e) {
//				// TODO 自动生成的 catch 块
//				e.printStackTrace();
//			}
	}
	public static String getWeekOfDate(Date date) {		
		String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };		
		Calendar cal = Calendar.getInstance();		
		cal.setTime(date);		
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;		
		if (w < 0)			
			w = 0;		
		return weekDays[w];	
		}
	
public static void main(String[] args) {
		Date date=new Date();
		String w=getWeekOfDate(date);
		System.out.println(w);
		String u1="星期五",u2="星期六";
		if(w.equals(u1)||w.equals(u2))
		{
			System.out.println("双休日期间,不予办理业务");
		}
		else
		{
			sale_Thread s1=new sale_Thread();
			sale_Thread s2=new sale_Thread();
			sale_Thread s3=new sale_Thread();
			sale_Thread s4=new sale_Thread();
			sale_Thread s5=new sale_Thread();
			Thread t1=new Thread(s1,"售票窗口1");
			Thread t2=new Thread(s2,"售票窗口2");
			Thread t3=new Thread(s3,"售票窗口3");
			Thread t4=new Thread(s4,"售票窗口4");
			Thread t5=new Thread(s5,"售票窗口5");
			t1.start();
			t2.start();
			t3.start();
			t4.start();
			t5.start();
		}
	}
}

方法二 实现Runnable接口

package Runable;


public class 售票系统2 
{
	public static int tickets=1000;
	protected synchronized static void use()
	{
			if(tickets>0)
			{
				System.out.println(Thread.currentThread().getName() +"售出第"+tickets--+"张票");
			}
//			try {
//				Thread.sleep(200);
//			} catch (InterruptedException e) {
//				// TODO 自动生成的 catch 块
//				e.printStackTrace();
//			}
	}
	public static void main(String[] args) {
		Runner1 runner1 = new Runner1();  
		Runner2 runner2 = new Runner2();  
		Runner3 runner3 = new Runner3();  
        Thread thread1 = new Thread(runner1,"售票窗口1");  
        Thread thread2 = new Thread(runner2,"售票窗口2");  
        Thread thread3 = new Thread(runner3,"售票窗口3"); 
        thread1.start();  
        thread2.start(); 
        thread3.start();
	}
}
class Runner1 extends 售票系统2 implements Runnable { 
     public void run() { 
    	 while(tickets>0)
         use();
    }  
}  
   
class Runner2 extends 售票系统2 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程  
     public void run() {
    	 while(tickets>0)
    	 use();
    }  
}

class Runner3 extends 售票系统2 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程  
    public void run() { 
    	while(tickets>0)
    	use();
   }  
}

案例九

方法一 继承Thread类

package Thticket;
/*
 * 继承Thread类方法售票*/
public class MyThread {
	public static void main(String[] args) {
		System.out.println("我是实现系统一");
		for(int i=1;i<6;i++) {
			new saleMyThread("第"+i+"窗口         ").start();
		}
	}
}
	class saleMyThread extends Thread{
		 private static int tic=100;
		//创建锁
		private static Object obj = new Object();
		//有参构造传入线程名
		public saleMyThread(String name) {
			super(name);
		}
		public saleMyThread() {

		}
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while (true) {
				try {
					//0.1秒
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				//同步锁
				synchronized (obj) {
					if (tic > 0) {
						System.out.println(Thread.currentThread().getName() + "售出第"
								+ tic + "票");
						tic--;
					}
					else {
						//车票售完
						System.out.println("车票已售完,下次请趁早...");
						System.exit(0);
					}
				}
			}
		}
		
	}

方法二 实现Runnable接口

package Runticket;
/*
 * 实现Runnable接口来售票*/
public class MyRunnable {
	public static void main(String[] args) {
		System.out.println("我是实现系统二");
		//得到对象
		saleMyRunnable mr=new saleMyRunnable();
		for(int i=1;i<6;i++){
        	new Thread(mr,"第"+i+"窗口       ").start();
        }
	}
}
class saleMyRunnable implements Runnable{
		//定义票的总数
	    private int tic = 100;
	    //定义一个线程同步对象
	    private Object obj = new Object();
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(true) {
				try {
					//0.1秒
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				//同步锁
				synchronized(obj) {
					if(tic > 0){
	                    System.out.println(Thread.currentThread().getName()+" 售出第   "+tic +"  张票");
	                    tic--;
	                }else{
	                    System.out.println("票已售完,请下次再来!");
	                    System.exit(0);
	                }
					
				}
			}
		}
	
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值