由卖票程序来理解线程

1、程序、进程、线程的概念(从计算机方面而言)

程序严格有序的指令集合。
进程计算机中已运行的程序的实体。 程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。
线程操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。是一个程序中的不同执行路径。
其实看了上面的定义,对这三个概念只是有了对其包含关系的理解,具体的含义还是懵懵懂懂,这个我觉得有必要去看一下操作系统方面的书籍。
在讨论卖票问题前,先介绍一个学到的感觉很不错的算法:时间片轮转调度算法
算法的含义:每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。如果在时间片结束时进程还在运行,则CPU占用将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾。

2、售票点卖票问题

考虑一个问题: 多个售票点,是否会出现卖出的都是同一张票?或者说只剩一张票,多个售票点是否都可以显示,是否都可以卖出去?
while (true){
	if (tickets > 0){
	<span style="white-space:pre">	</span>sell;
		tickets--;
	}
}
如果应用上面的程序,多个售票点售票可能会出现问题,因为 CPU可能会在while中的任何一行语句执行完之后跳转到另一个线程中去 ,这样可能会导致票已经在一个售票点卖出去了,而票数未减少,在其它售票点又卖出了同样的一张票。
卖票的问题可以归结为这样一个问题: 多个线程处理共同享有的资源,当一个线程在占用处理资源时,其他线程不能够再去占用处理该资源,必须等到结束时大家再一起开始竞争
Java中提供了 关键字synchronized(同步)来处理这样的问题,其 可修饰对象方法或是代码块,使用方法为
synchronized (类对象名 a){
	...//代码块
}
上述代码的含义是:
判断a是否已被其他线程锁定
1)是,当前线程进入等待,等候锁定被释放;
2)否,锁定a对象并执行代码块,直到释放锁定为止。
注意:释放锁定后,所有的线程会共同竞争对a的锁定权(包括刚执行完的线程)

2.1 线程的定义方式

线程有两种定义方式
(1)继承自Thread。需重写run()方法,在main中生成该子类的对象,并调用start()方法(其会自动调用run()方法)
class A extends Thread{
	//int tickets = 50;		//设置票数//【此处需修改为静态变量】
	public static int tickets = 100; 
	public static String s = new String("卖票");	//定义要锁定的对象
	
	public void run() {
		while (true){
			synchronized (s){
				if (tickets > 0){
					System.out.println(Thread.currentThread().getName()+"正在卖出车票"+tickets);
					tickets--;
					}
				else {
					break;
					}
			}
		}
	}
}
(2)实现接口Runnable。需重写run()方法,在main中生成该子类的对象,并将其作为参数来构建Thread对象,调用start()方法
/*售票点卖票问题
 * */
class B extends Thread{
	int tickets = 100;		//设置票数//【此处需修改为静态变量】
	//public static int tickets = 100; //无需设置为static,因生成Thread对象的参数是一样的
	//public static String s = new String("卖票");	//定义要锁定的对象//无需static,原因同上
	String s = new String("卖票");
}

2.2 售票点卖票程序

下面是实现多个售票点卖票的代码:
/*售票点卖票问题
 * */
public class TestTickets {
	
	public static void main(String[] args) {
		A a1 = new A();
		A a2 = new A();
		a1.start();
		//a1.start();		//error,同一个对象不能运行两次a.start();不然会抛出异常 java.lang.IllegalThreadStateException
		a2.start();
		//【上面的a1、a2两个对象,实际上产生了两个tickets常量,而非同一个,故应改为static int】
	}
}
/*运行结果:【针对的是第一种线程构建方式】
【1、不加关键字synchronized时的状况:出现问题】
Thread-0Thread-1正在卖出车票50
正在卖出车票50
Thread-0Thread-1正在卖出车票49
Thread-0正在卖出车票49
【2、添加之后的状况:解决了上面的问题,但是依然存在同一张票卖多次的问题】
Thread-0正在卖出车票50
Thread-0正在卖出车票49
Thread-1正在卖出车票50
Thread-1正在卖出车票49
【原因:占用处理的不是同一个资源:将属性和要锁定的对象改为static】
【3、修改之后程序运行无误,两条线程交叉进行,由CPU进行分配】
 */
   线程这个问题很有意思,以后要好好研究一下。
PS:CPU不能同时执行多项任务,是处在不断切换的状态,只是它的运算速度实在太快,使我们产生了它可以同时进行多项操作的错觉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值