由卖票程序来理解线程

来源:互联网 发布:做网络销售公司好做吗 编辑:程序博客网 时间:2024/04/30 02:20

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.IllegalThreadStateExceptiona2.start();//【上面的a1、a2两个对象,实际上产生了两个tickets常量,而非同一个,故应改为static int】}}/*运行结果:【针对的是第一种线程构建方式】【1、不加关键字synchronized时的状况:出现问题】Thread-0Thread-1正在卖出车票50正在卖出车票50Thread-0Thread-1正在卖出车票49Thread-0正在卖出车票49【2、添加之后的状况:解决了上面的问题,但是依然存在同一张票卖多次的问题】Thread-0正在卖出车票50Thread-0正在卖出车票49Thread-1正在卖出车票50Thread-1正在卖出车票49【原因:占用处理的不是同一个资源:将属性和要锁定的对象改为static】【3、修改之后程序运行无误,两条线程交叉进行,由CPU进行分配】 */
   线程这个问题很有意思,以后要好好研究一下。
PS:CPU不能同时执行多项任务,是处在不断切换的状态,只是它的运算速度实在太快,使我们产生了它可以同时进行多项操作的错觉。
0 0
原创粉丝点击