多线程解决现实中的抢票问题(初级)

来源:互联网 发布:微信二级分销系统源码 编辑:程序博客网 时间:2024/05/29 15:08

多线程解决现实中的抢票问题

以下为两种解决方式:

1.实现Runnable接口
2.继承自Thread

1.第一种方法(正确)

Public class A extends Thread{      Public static int tickets = 100;      Public static String str  =  new String(“哈哈”)Public void run(){        While(true){           Synchronized( str ){              If  (tickets > 0 ){                 System.out.println(“第%s个线程卖出了第%d张票, Thread.currentThread().getName(),tickets”);--tickets;               }            }         }       }}Public class Main {   Public static void main ( String [ ] args ){     A aa1 = new A ();     aa1.start();     A aa2 = new A();     aa2.start();   }}

解释:两个线程两个对象aa1 和 aa2 ,两个.start()方法,开启了两个run()方法,所以如果想让它卖一种票就对tickets进行静态处理,如果还想让两个线程互斥,则要统一str,因为是两个对象锁定各自的str,要对其进行静态处理,因为Synchronized( str ){ }该方法。

2.用第二种方法来实现卖票(正确)

Public class A implesant Runnable{Publc  int  tickets = 100;      string  str  =  new  String(“哈哈”);  Void run (){       While(t){         Synchronichedstr){         If(tickets > 0 ){System.out.println(“第%s个线程卖掉了第%d张票”);                -- tickets;  } }     }   } }Public class Main {  Public static void main(String [] args){A aa = new A(); Thread tt1 = new Thread(aa);tt.start();Thread tt2 = new Thread(aa);tt.strat();  }}

解释:
第二种方法为什么不需要static 而第一种方法需要
A aa = new A();
Thread t = new Thread(aa);
用一个aa对象可以同时构建多个线程,一个对象就默认共享同一个资源,所以就是卖同一张票。

所以相比较而言,最好用第二种方法,创建一个对象就可以同时构建多个线程,并且还共享同一个资源,也节省对象资源。

3.错误示范1

Public class A implesant Runnable{Publc  int  tickets = 100;    string  str  =  new  String(“哈哈”);  Void  run (){      While(true){         {          Synchronichedstr){         If(tickets > 0 ){System.out.println(“第%s个线程卖掉了第%d张票”);                -- tickets;  } }   } }Public class Main {  Public static void main(String [] args){A aa = new A(); Thread tt1 = new Thread(aa);tt.start();Thread tt2 = new Thread(aa);tt.strat();  }}

那么我们试想以下可不可以这样写呢?
这样写会导致什么情况呢?
答:会导致只有一个线程在运行,run方法直接被其中一个线程霸占后另一个不能调用run方法,不让别的线程卖票了。
所以这种写法是错误的,不合理的。

4.错误示范2

Public class A implesant Runnable{ Publc  int  tickets = 100;    Void  run (){      string  str  =  new  String(“哈哈”);       While(true){         {        Synchronichedstr){         If(tickets > 0 ){System.out.println(“第%s个线程卖掉了第%d张票”);                -- tickets;  } }   } }Public class Main {  Public static void main(String [] args){A aa = new A(); Thread tt1 = new Thread(aa);tt.start();Thread tt2 = new Thread(aa);tt.strat();  }}

这种写法也是不对的,因为string str = new String(“哈哈”); 在run()方法里面,虽然Thread tt1 = new Thread(aa);和Thread tt2 = new Thread(aa);都调用同一个类对象,但是run方法分别被调用一次,所以str为两种,所以就是各卖各的票,没有互斥。所以这种写法依然不合理。

5.错误示范3

Public class A implesant Runnable{ Publc  int  tickets = 100;string  str  =  new  String(“哈哈”);     Void  run (){      string  str  =  new  String(“哈哈”); //可以定义一个局部变量,局部变量和属性名字相同      While(true){         {         If(tickets > 0 ){System.out.println(“第%s个线程卖掉了第%d张票”);                -- tickets;  } }   } }Public class Main {  Public static void main(String [] args){A aa = new A(); Thread tt1 = new Thread(aa);tt.start();Thread tt2 = new Thread(aa);tt.strat();  }}

在方法内部定义一个局部变量,局部变量是可以和属性名字相同的,那么就意味着run()方法中str是局部变量的str,所以依然各卖各的票,没有互斥。所以这种写法依然不合理。
证明:

Class A{ Int i = 10 ;  Public void f(){Int  i = 20;System.out.println(“i =  ”  +  i );   }}Public class Main{  Public static void main(String [] args){    New A().f();  }}

运行结果为20,以此证明run()方法中str是局部变量的str.

注意看,这种方式呢?

Public class A implesant Runnable{ Publc  int  tickets = 100;    Public void  run (){      String  str  =  “哈哈”;       While(true){         {        Synchronichedstr){         If(tickets > 0 ){System.out.println(“第%s个线程卖掉了第%d张票”);                -- tickets;  } }   } }Public class Main {  Public static void main(String [] args){A aa = new A(); Thread tt1 = new Thread(aa);tt.start();Thread tt2 = new Thread(aa);tt.strat();  }}

答:这种写法是正确的
解释:
因为String str = new String(“哈哈”);是把数据放在堆区,
而String str = “哈哈”;是把数据放在数据区,数据区如果数值相同就是指向同一个对象。
所以即使String str = “哈哈”在run函数里面,但是两个线程指向的同一个str,就能够互斥。
因此写法正确。

希望对初学者学习线程有所帮助!谢谢观看!
原创粉丝点击