您的位置:首页 > 其它

多线程——用创建线程的两种方式分别解决经典窗口卖票问题

2016-08-19 20:33 525 查看
/**
* 窗口卖票经典实例,第一种继承Thread类多线程进行解决
*
*
* 需求:四个窗口同时卖票。票数100张
*
* 分析:
* 一个有100张票,卖票的动作是四个窗口所使用的,并且是同时进行的,那么就要使用多线程技术。
*
* 怎么创建线程?
* 1.继承Thread类,并且重写run方法。
* 2.将卖票的动作定义到run方法当中。
* */
package com.work.wor01;

class Ticket extends Thread{
private static int num = 100;//声明成静态变量,利用静态数据的共享性,避免卖重票
//private int num = 100;如果不声明成静态变量,那么四个窗口每个窗口都会卖100张票,导致重复卖票。

@Override
public void run() {
while(true){     //因为他要运行多少次是不确定的,具体要看cpu的调用
if(num>0){   //卖票的过程只能是正数,所以在这里放了一个判断
System.out.println(Thread.currentThread().getName()+"...sale"+num--);
}else{
break;
}
}
}
}
public class ThreadTicket {
public static void main(String[] args) {
Ticket t1 = new Ticket();
Ticket t2 = new Ticket();
Ticket t3 = new Ticket();
Ticket t4 = new Ticket();

t1.start();
t2.start();
t3.start();
t4.start();
}
}
</pre><pre code_snippet_id="1840947" snippet_file_name="blog_20160819_4_1957035" name="code" class="java">
</pre><pre code_snippet_id="1840947" snippet_file_name="blog_20160819_5_7671655" name="code" class="java"><pre name="code" class="java">/**
* 将卖票的例子通过另外一种线程创建的方式写出来。
* 创建线程方式二:
* 1.定义一个类,让他去实现runnable接口。
* 2.重写runnable接口当中的run方法,然后将线程将要运行的方法存储到run方法当中来。
* 3.创建该接口的实现类的对象。
* 4.通过Thread类进行线程的创建,并且将runnable接口的实现类的对象作为Thread的构造函数的参数传递进去。
* 5.调用Thread类当中的start方法去运行线程。
*
* 为什么传递?
* 当线程对象创建时,就要明确运行哪个run方法(明确线程任务),那这个run方法就要明确是被哪个对象所调用的。
* 所以我们就可以将run方法所属的对象传递到Thread的构造函数。
*
* runnable接口的由来其实就是线程	中的任务进行了对象的封装,将线程任务进行封装之后,
* 通过runnable接口可以降低耦合性。
*
* 如果继承了Thread类,就要去重写他的run方法,那么thread类的子类就封装了线程的任务,
* 而且他本身还是一个线程对象,这就是任务和对象耦合性过高,不利于拓展。
*
*
* 第一种方式:
* class Demo extends Thread{
* 		public void run(){
*        //线程的任务
*     }
* }
*
* 创建线程:
* Demo d = new Demo();   //带有具体的任务的线程的对象
* d.start();
* 这个对象是一个线程的对象,任务就是与他绑定的任务,那么它还能绑定其他任务么?
* 答:不能,这个问题怎么解决,用第二种方式创建线程。
*
* 第二种方式创建线程:实现Runnable接口
* class Demo implements Runnable{
* 		public void run(){
*        //线程的任务
* 		}
* }
* 创建并运行线程
* Demo d = new Demo();    //这是一个线程任务的对象
* Thread t = new Thread(d);    //布置了任务到线程对象当中。
* t.start();
*
* 以后在写多线程的时候,尽量用第二种方式:实现Runnable接口。
* 避免了单继承的局限性。
*
* 通过画图分析,分析错票产生的原因:
* 已经判断为票数了,线程被阻塞了,先一次被切换到不需要判断了。
* 局部变量不会出现数字错乱的现象,而成员变量会出现数组出现负数的现象。
*
*
* */
package com.work.wor01;

class Ticket1 implements Runnable{
private int num = 100;
@Override
public void run() {
while(true){
if(num>0){
//				try {
//				在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)会产生负数票
//					Thread.sleep(10);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
System.out.println(Thread.currentThread().getName()+"...sale"+num--);
}else{
break;
}
}
}
}

public class ThreadTicket02 {
public static void main(String[] args) {
Ticket1 t = new Ticket1();
//Thread类的对象和Thread类的子类的对象都是线程的对象。
//但是t并不是线程的对象。
//向四个线程当中传入的是同一个t对象,是因为线程执行的是同样的任务。
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);

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



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程
相关文章推荐