多线程编程(四)--多线程练习

一、多线程练习

某电影院正在上映贺岁大片,共有100张票,而它有三个售票窗口售票,请设计一个程序模拟该电影院售票。

提示:两种方法实现(1)继承Thread 类 (2)实现Runnable接口

(1)继承Thread 类

package cn.itcast_06;

public class SellTicketThread extends Thread{
	// 定义100张票
	//int ticketNum=100;
	
	private static int ticketNum=100;
	public void run(){
		// 定义100张票
		//int ticketNum=100;
		while(true){
			if(ticketNum>0){
				System.out.println(getName()+":正在售票"+(ticketNum--)+"张票");
			}
		}
	}
}

测试类:

package cn.itcast_06;
/**
 * 某电影院正在上映贺岁大片,共有100张票,
 * 而他又三个售票窗口,请设计一个程序模拟电影院售票
 * @author jack
 *
 */
public class SaleTickThreadDemo {

	public static void main(String[] args) {
		//创建三个线程对象
		SellTicketThread st1=new SellTicketThread();
		SellTicketThread st2=new SellTicketThread();
		SellTicketThread st3=new SellTicketThread();
		
		st1.setName("窗口1");
		st2.setName("窗口2");
		st3.setName("窗口3");
		
		st1.start();
		st2.start();
		st3.start();
		
		ThreadLocal tl=new ThreadLocal();
	}

}

运行结果(每次运行结果并不相同):

窗口1:正在售票100张票
窗口3:正在售票98张票
窗口3:正在售票97张票
窗口3:正在售票96张票
窗口3:正在售票95张票
窗口3:正在售票94张票
窗口3:正在售票93张票
窗口3:正在售票92张票
窗口3:正在售票91张票
窗口3:正在售票90张票
窗口3:正在售票89张票
窗口3:正在售票88张票
窗口3:正在售票87张票
窗口3:正在售票86张票
窗口3:正在售票85张票
窗口3:正在售票84张票
窗口3:正在售票83张票
窗口3:正在售票82张票
窗口3:正在售票81张票
窗口3:正在售票80张票
窗口3:正在售票79张票
窗口3:正在售票78张票
窗口3:正在售票77张票
窗口3:正在售票76张票
窗口3:正在售票75张票
窗口3:正在售票74张票
窗口3:正在售票73张票
窗口3:正在售票72张票
窗口3:正在售票71张票
窗口3:正在售票70张票
窗口3:正在售票69张票
窗口3:正在售票68张票
窗口3:正在售票67张票
窗口3:正在售票66张票
窗口3:正在售票65张票
窗口3:正在售票64张票
窗口3:正在售票63张票
窗口3:正在售票62张票
窗口3:正在售票61张票
窗口3:正在售票60张票
窗口3:正在售票59张票
窗口3:正在售票58张票
窗口3:正在售票57张票
窗口3:正在售票56张票
窗口3:正在售票55张票
窗口3:正在售票54张票
窗口3:正在售票53张票
窗口3:正在售票52张票
窗口3:正在售票51张票
窗口3:正在售票50张票
窗口3:正在售票49张票
窗口3:正在售票48张票
窗口3:正在售票47张票
窗口3:正在售票46张票
窗口3:正在售票45张票
窗口3:正在售票44张票
窗口3:正在售票43张票
窗口3:正在售票42张票
窗口3:正在售票41张票
窗口3:正在售票40张票
窗口3:正在售票39张票
窗口3:正在售票38张票
窗口3:正在售票37张票
窗口3:正在售票36张票
窗口3:正在售票35张票
窗口3:正在售票34张票
窗口3:正在售票33张票
窗口3:正在售票32张票
窗口3:正在售票31张票
窗口3:正在售票30张票
窗口3:正在售票29张票
窗口3:正在售票28张票
窗口3:正在售票27张票
窗口3:正在售票26张票
窗口3:正在售票25张票
窗口3:正在售票24张票
窗口3:正在售票23张票
窗口3:正在售票22张票
窗口3:正在售票21张票
窗口3:正在售票20张票
窗口3:正在售票19张票
窗口3:正在售票18张票
窗口3:正在售票17张票
窗口3:正在售票16张票
窗口3:正在售票15张票
窗口3:正在售票14张票
窗口3:正在售票13张票
窗口3:正在售票12张票
窗口3:正在售票11张票
窗口3:正在售票10张票
窗口3:正在售票9张票
窗口3:正在售票8张票
窗口3:正在售票7张票
窗口3:正在售票6张票
窗口3:正在售票5张票
窗口3:正在售票4张票
窗口3:正在售票3张票
窗口3:正在售票2张票
窗口3:正在售票1张票
窗口2:正在售票99张票


(2)实现Runnable接口

package cn.itcast_07;

public class SellTicketRunnable implements Runnable {
	private int ticketNum=100;
	@Override
	public void run() {
		while(true){
			if(ticketNum>0){
				System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticketNum--)+"张票");
			}
		}
	}

}

测试类:

package cn.itcast_07;

/**
 * 实现Runnable接口的方式实现
 * @author jack
 *
 */
public class SellTicketRunnableDemo {

	public static void main(String[] args) {
		//创建资源对象
		SellTicketRunnable st=new SellTicketRunnable();
		
		//创建三个线程对象
		Thread t1=new Thread(st,"窗口1");
		Thread t2=new Thread(st,"窗口2");
		Thread t3=new Thread(st,"窗口3");
		

		t1.start();
		t2.start();
		t3.start();
	}

}

运行结果:

窗口1正在出售第100张票
窗口1正在出售第97张票
窗口1正在出售第96张票
窗口1正在出售第95张票
窗口1正在出售第94张票
窗口1正在出售第93张票
窗口1正在出售第92张票
窗口1正在出售第91张票
窗口1正在出售第90张票
窗口3正在出售第98张票
窗口2正在出售第99张票
窗口2正在出售第87张票
窗口2正在出售第86张票
窗口3正在出售第88张票
窗口1正在出售第89张票
窗口3正在出售第84张票
窗口2正在出售第85张票
窗口3正在出售第82张票
窗口1正在出售第83张票
窗口3正在出售第80张票
窗口2正在出售第81张票
窗口3正在出售第78张票
窗口3正在出售第76张票
窗口3正在出售第75张票
窗口3正在出售第74张票
窗口3正在出售第73张票
窗口1正在出售第79张票
窗口3正在出售第72张票
窗口3正在出售第70张票
窗口3正在出售第69张票
窗口1正在出售第71张票
窗口1正在出售第67张票
窗口1正在出售第66张票
窗口1正在出售第65张票
窗口1正在出售第64张票
窗口1正在出售第63张票
窗口1正在出售第62张票
窗口1正在出售第61张票
窗口1正在出售第60张票
窗口1正在出售第59张票
窗口1正在出售第58张票
窗口2正在出售第77张票
窗口1正在出售第57张票
窗口3正在出售第68张票
窗口1正在出售第55张票
窗口2正在出售第56张票
窗口2正在出售第52张票
窗口2正在出售第51张票
窗口2正在出售第50张票
窗口2正在出售第49张票
窗口2正在出售第48张票
窗口2正在出售第47张票
窗口2正在出售第46张票
窗口2正在出售第45张票
窗口2正在出售第44张票
窗口2正在出售第43张票
窗口2正在出售第42张票
窗口1正在出售第53张票
窗口1正在出售第40张票
窗口3正在出售第54张票
窗口3正在出售第38张票
窗口1正在出售第39张票
窗口2正在出售第41张票
窗口1正在出售第36张票
窗口1正在出售第34张票
窗口3正在出售第37张票
窗口1正在出售第33张票
窗口2正在出售第35张票
窗口1正在出售第31张票
窗口1正在出售第29张票
窗口1正在出售第28张票
窗口1正在出售第27张票
窗口1正在出售第26张票
窗口3正在出售第32张票
窗口1正在出售第25张票
窗口2正在出售第30张票
窗口1正在出售第23张票
窗口3正在出售第24张票
窗口1正在出售第21张票
窗口2正在出售第22张票
窗口1正在出售第19张票
窗口1正在出售第17张票
窗口1正在出售第16张票
窗口1正在出售第15张票
窗口1正在出售第14张票
窗口1正在出售第13张票
窗口1正在出售第12张票
窗口1正在出售第11张票
窗口1正在出售第10张票
窗口1正在出售第9张票
窗口1正在出售第8张票
窗口1正在出售第7张票
窗口1正在出售第6张票
窗口1正在出售第5张票
窗口1正在出售第4张票
窗口3正在出售第20张票
窗口1正在出售第3张票
窗口2正在出售第18张票
窗口1正在出售第1张票
窗口3正在出售第2张票

上面的电影院售票程序,从表面上看好像并没有任何问题。但是在真实的网络中,售票时网络是不能实时传输的,总是存在延迟的情况,所以在售出一张票后总是需要一点时间的延迟。

(3)实现Runnable接口(在(2)的基础上修改卖票程序)--每次卖票延迟100毫秒

package cn.itcast_07;

public class SellTicketRunnable2 implements Runnable {
	private int ticketNum=100;
	@Override
	public void run() {
		while(true){
			if(ticketNum>0){
				//为了模拟更真实的场景我们稍作休息
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticketNum--)+"张票");
			}
		}
	}

}
测试类:
package cn.itcast_07;

/**
 * 实现Runnable接口的方式实现
 * @author jack
 *
 */
public class SellTicketRunnable2Demo {

	public static void main(String[] args) {
		//创建资源对象
		SellTicketRunnable2 st=new SellTicketRunnable2();
		
		//创建三个线程对象
		Thread t1=new Thread(st,"窗口1");
		Thread t2=new Thread(st,"窗口2");
		Thread t3=new Thread(st,"窗口3");
		

		t1.start();
		t2.start();
		t3.start();
	}

}

运行结果:

第一次:

窗口2正在出售第100张票
窗口1正在出售第99张票
窗口3正在出售第99张票
窗口1正在出售第98张票
窗口2正在出售第96张票
窗口3正在出售第97张票
窗口1正在出售第95张票
窗口2正在出售第94张票
窗口3正在出售第93张票
窗口1正在出售第92张票
窗口3正在出售第91张票
窗口2正在出售第90张票
窗口1正在出售第89张票
窗口3正在出售第88张票
窗口2正在出售第87张票
窗口1正在出售第86张票
窗口3正在出售第85张票
窗口2正在出售第84张票
窗口1正在出售第83张票
窗口3正在出售第82张票
窗口2正在出售第81张票
窗口1正在出售第80张票
窗口3正在出售第79张票
窗口2正在出售第78张票
窗口1正在出售第77张票
窗口3正在出售第76张票
窗口2正在出售第75张票
窗口1正在出售第74张票
窗口3正在出售第73张票
窗口2正在出售第72张票
窗口1正在出售第71张票
窗口3正在出售第70张票
窗口2正在出售第69张票
窗口1正在出售第68张票
窗口3正在出售第67张票
窗口2正在出售第66张票
窗口1正在出售第65张票
窗口3正在出售第64张票
窗口2正在出售第63张票
窗口1正在出售第62张票
窗口3正在出售第61张票
窗口2正在出售第60张票
窗口1正在出售第59张票
窗口3正在出售第58张票
窗口2正在出售第57张票
窗口1正在出售第56张票
窗口2正在出售第55张票
窗口3正在出售第54张票
窗口1正在出售第53张票
窗口2正在出售第52张票
窗口3正在出售第51张票
窗口1正在出售第50张票
窗口2正在出售第49张票
窗口3正在出售第48张票
窗口1正在出售第47张票
窗口2正在出售第46张票
窗口3正在出售第45张票
窗口1正在出售第44张票
窗口3正在出售第43张票
窗口2正在出售第42张票
窗口1正在出售第41张票
窗口2正在出售第40张票
窗口3正在出售第39张票
窗口1正在出售第38张票
窗口2正在出售第37张票
窗口3正在出售第36张票
窗口1正在出售第35张票
窗口3正在出售第34张票
窗口2正在出售第33张票
窗口1正在出售第32张票
窗口3正在出售第31张票
窗口2正在出售第30张票
窗口1正在出售第29张票
窗口3正在出售第28张票
窗口2正在出售第27张票
窗口1正在出售第26张票
窗口3正在出售第25张票
窗口2正在出售第24张票
窗口1正在出售第23张票
窗口3正在出售第22张票
窗口2正在出售第21张票
窗口3正在出售第20张票
窗口2正在出售第19张票
窗口1正在出售第18张票
窗口3正在出售第17张票
窗口2正在出售第16张票
窗口1正在出售第15张票
窗口3正在出售第14张票
窗口2正在出售第13张票
窗口1正在出售第12张票
窗口3正在出售第11张票
窗口2正在出售第10张票
窗口1正在出售第9张票
窗口3正在出售第8张票
窗口2正在出售第7张票
窗口1正在出售第6张票
窗口3正在出售第5张票
窗口2正在出售第4张票
窗口1正在出售第3张票
窗口3正在出售第2张票
窗口2正在出售第1张票
窗口1正在出售第0张票
窗口3正在出售第-1张票
运行第二次:
窗口3正在出售第100张票
窗口1正在出售第99张票
窗口2正在出售第98张票
窗口3正在出售第97张票
窗口1正在出售第96张票
窗口2正在出售第95张票
窗口3正在出售第94张票
窗口1正在出售第93张票
窗口3正在出售第92张票
窗口2正在出售第91张票
窗口1正在出售第90张票
窗口3正在出售第89张票
窗口1正在出售第88张票
窗口2正在出售第87张票
窗口1正在出售第86张票
窗口3正在出售第85张票
窗口2正在出售第84张票
窗口1正在出售第83张票
窗口3正在出售第82张票
窗口2正在出售第81张票
窗口1正在出售第80张票
窗口3正在出售第79张票
窗口1正在出售第78张票
窗口2正在出售第77张票
窗口3正在出售第76张票
窗口1正在出售第75张票
窗口2正在出售第74张票
窗口3正在出售第73张票
窗口1正在出售第72张票
窗口2正在出售第71张票
窗口3正在出售第70张票
窗口1正在出售第69张票
窗口2正在出售第68张票
窗口1正在出售第67张票
窗口3正在出售第66张票
窗口2正在出售第65张票
窗口1正在出售第64张票
窗口3正在出售第63张票
窗口2正在出售第62张票
窗口1正在出售第61张票
窗口3正在出售第60张票
窗口2正在出售第59张票
窗口1正在出售第58张票
窗口3正在出售第57张票
窗口2正在出售第56张票
窗口1正在出售第55张票
窗口3正在出售第54张票
窗口2正在出售第53张票
窗口3正在出售第52张票
窗口1正在出售第51张票
窗口2正在出售第50张票
窗口3正在出售第49张票
窗口1正在出售第48张票
窗口2正在出售第47张票
窗口3正在出售第46张票
窗口1正在出售第45张票
窗口2正在出售第44张票
窗口3正在出售第43张票
窗口1正在出售第42张票
窗口3正在出售第41张票
窗口2正在出售第40张票
窗口1正在出售第39张票
窗口3正在出售第38张票
窗口1正在出售第37张票
窗口2正在出售第36张票
窗口1正在出售第35张票
窗口2正在出售第34张票
窗口3正在出售第33张票
窗口1正在出售第32张票
窗口3正在出售第31张票
窗口1正在出售第30张票
窗口2正在出售第29张票
窗口3正在出售第28张票
窗口1正在出售第27张票
窗口2正在出售第26张票
窗口3正在出售第25张票
窗口1正在出售第24张票
窗口2正在出售第23张票
窗口3正在出售第22张票
窗口1正在出售第21张票
窗口2正在出售第20张票
窗口3正在出售第19张票
窗口1正在出售第18张票
窗口2正在出售第17张票
窗口3正在出售第16张票
窗口1正在出售第15张票
窗口3正在出售第14张票
窗口2正在出售第13张票
窗口1正在出售第12张票
窗口3正在出售第11张票
窗口1正在出售第10张票
窗口2正在出售第9张票
窗口1正在出售第8张票
窗口3正在出售第7张票
窗口1正在出售第6张票
窗口2正在出售第5张票
窗口3正在出售第4张票
窗口1正在出售第3张票
窗口2正在出售第2张票
窗口1正在出售第1张票
窗口3正在出售第0张票
窗口2正在出售第-1张票

第三次运行结果:

窗口3正在出售第100张票
窗口2正在出售第99张票
窗口1正在出售第98张票
窗口3正在出售第97张票
窗口2正在出售第96张票
窗口1正在出售第95张票
窗口3正在出售第94张票
窗口2正在出售第93张票
窗口3正在出售第92张票
窗口1正在出售第91张票
窗口3正在出售第90张票
窗口2正在出售第89张票
窗口1正在出售第88张票
窗口3正在出售第87张票
窗口2正在出售第86张票
窗口1正在出售第85张票
窗口3正在出售第84张票
窗口2正在出售第83张票
窗口1正在出售第82张票
窗口3正在出售第81张票
窗口2正在出售第80张票
窗口3正在出售第79张票
窗口1正在出售第78张票
窗口2正在出售第77张票
窗口3正在出售第76张票
窗口3正在出售第75张票
窗口1正在出售第74张票
窗口2正在出售第73张票
窗口3正在出售第72张票
窗口2正在出售第71张票
窗口1正在出售第70张票
窗口3正在出售第69张票
窗口2正在出售第68张票
窗口1正在出售第67张票
窗口3正在出售第66张票
窗口2正在出售第65张票
窗口1正在出售第64张票
窗口3正在出售第63张票
窗口2正在出售第62张票
窗口3正在出售第61张票
窗口1正在出售第60张票
窗口3正在出售第59张票
窗口2正在出售第58张票
窗口1正在出售第57张票
窗口3正在出售第56张票
窗口2正在出售第55张票
窗口1正在出售第54张票
窗口3正在出售第53张票
窗口2正在出售第52张票
窗口3正在出售第51张票
窗口1正在出售第50张票
窗口3正在出售第49张票
窗口2正在出售第48张票
窗口1正在出售第47张票
窗口3正在出售第46张票
窗口2正在出售第45张票
窗口1正在出售第44张票
窗口3正在出售第43张票
窗口2正在出售第42张票
窗口3正在出售第41张票
窗口1正在出售第40张票
窗口2正在出售第39张票
窗口3正在出售第38张票
窗口1正在出售第37张票
窗口2正在出售第36张票
窗口3正在出售第35张票
窗口1正在出售第34张票
窗口3正在出售第33张票
窗口2正在出售第32张票
窗口1正在出售第31张票
窗口3正在出售第30张票
窗口2正在出售第29张票
窗口3正在出售第28张票
窗口1正在出售第27张票
窗口2正在出售第26张票
窗口3正在出售第25张票
窗口1正在出售第24张票
窗口2正在出售第23张票
窗口3正在出售第22张票
窗口1正在出售第21张票
窗口3正在出售第20张票
窗口2正在出售第19张票
窗口1正在出售第18张票
窗口3正在出售第17张票
窗口2正在出售第16张票
窗口3正在出售第15张票
窗口1正在出售第14张票
窗口2正在出售第13张票
窗口3正在出售第12张票
窗口2正在出售第11张票
窗口3正在出售第10张票
窗口1正在出售第9张票
窗口2正在出售第8张票
窗口3正在出售第7张票
窗口1正在出售第6张票
窗口3正在出售第5张票
窗口2正在出售第4张票
窗口1正在出售第3张票
窗口3正在出售第2张票
窗口2正在出售第1张票
窗口3正在出售第0张票
窗口1正在出售第-1张票

从几次运行结果发现改进后的售票程序出了几个问题:

a)相同的票卖了多次------cpu的一次操作必须是原子性的

b)还出现了负数票和0数票-----随机性和延迟导致的

注意:线程安全问题在理想状态下是不容易出现的,但一旦出现对软件的影响是非常大的。

解决线程安全问题的思想:

1)首先想为什么会出现问题?(也是我们判断是否有问题的标准)

是否有多线程环境

是否有共享数据

是否有多条语句操作共享数据

2)如何解决多线程安全问题

基本思路:让程序没有安全问题的环境

怎么实现呢

把多个语句操作共享数据的代码给锁起来,让任意时刻只能有有一个线程访问


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值