java 多线程简单例子

转载自博客园:https://www.cnblogs.com/nn369/p/8043303.html

实现线程的方式是一,继承Thread类,重写父类的run()方法

二,实现接口Runnable中的run()方法。

下面是简单的例子

例子1:银行存取钱问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package  com.direct.demo;
 
public  class  Bank {
     private  static  int  money;
     public  int  getMoney(){
         return  money;
     }
     public  void  saveMoney( int  m){
         synchronized  ( this ) {
             System.out.println( "存钱后的总金额:" +(money+=m));         
         }
     }
     public  void  drawMoney( int  m){
         synchronized  ( this ) {
             Bank bank =  new  Bank();
             if  (bank.getMoney()<= 0 ) {
                 System.out.println( "没得钱,取个pi" );
             } else  {
                 System.out.println( "取钱后剩的总金额:" +(money-=m));        
             }
         }
     }
     
     public  static  void  main(String[] args) {
         Man m1 =  new  Man();
         Women w =  new  Women();
         Thread t1 =  new  Thread(m1);
         Thread t2 =  new  Thread(m1);
         Thread t3 =  new  Thread(m1);
         Thread t4 =  new  Thread(w);
         Thread t5 =  new  Thread(w);
         Thread t6 =  new  Thread(w);
         t1.start();
         t2.start();
         t3.start();
         t4.start();
         t5.start();
         t6.start();
         }
 
}
 
class  Man  implements  Runnable{
     private  Bank bank =  new  Bank();
 
     public  void  run() {
         int  m =  100 ;
         int  i= 0 ;
         while  (i< 5 ) {
                 bank.saveMoney(m);
                 i++;
                 try  {
                     Thread.sleep( 100 );
                 catch  (InterruptedException e) {
                     e.printStackTrace();
                 }  
         }
     }
}
class  Women  implements  Runnable{
     private  Bank bank =  new  Bank();
 
     public  void  run() {
         int  m =  100 ;
         int  i= 0 ;
         //bank.getMoney()>0
         while  (i< 5 ) {
                     bank.drawMoney(m);
                 try  {
                     Thread.sleep( 100 );
                 catch  (InterruptedException e) {
                     e.printStackTrace();
                 }
         i++;
         }
     }
     
}

  例子2:生产者与消费者问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package  com.direct.demo;
 
public  class  Clerk {
     private  int  product = - 1 ;
     
     //这个方法由生产者调用
     public  synchronized  void  setProduct( int  product){
         if  ( this .product != - 1 ) {
             try  {
                 wait();
             catch  (InterruptedException e) {
                 e.printStackTrace();
             }
         }
         this .product = product;
         System.out.printf( "生产者设定 (%d)%n" , this .product);
         notify();
     }
     
     //这个方法由消费者调用
     public  synchronized  int  getProduct(){
         if  ( this .product==- 1 ) {
             try  {
                 wait();
             catch  (InterruptedException e) {
                 e.printStackTrace();
             }
         }
         int  p =  this .product;
         System.out.printf( "消费者取走 (%d)%n" , this .product);
         this .product = - 1 ;
         notify();
         return  p;
     }
 
     public  static  void  main(String[] args) {
         Clerk clerk =  new  Clerk();
         new  Thread( new  ProducerInt(clerk)).start();
         new  Thread( new  ConsumerInt(clerk)).start();
     }
     
}
 
class   ProducerInt  implements  Runnable{
     private  Clerk clerk;
     public  ProducerInt(Clerk clerk){
         this .clerk = clerk;
     }
     public  void  run() {
         System.out.println( "生产者开始生产整数了.................." );
         for  ( int  product =  1 ; product <=  10 ; product++) {
             try  {
                 Thread.sleep(( int )Math.random()* 300 );
             catch  (InterruptedException e) {
                 e.printStackTrace();
             }
             clerk.setProduct(product);
         }
     }
     
}
 
class  ConsumerInt  implements  Runnable{
     private  Clerk clerk;
     public  ConsumerInt(Clerk clerk){
         this .clerk = clerk;
     }
     public  void  run() {
         System.out.println( "消费者开始消耗整数........" );
         for  ( int  i =  1 ; i <= 10  ; i++) {
             try  {
                 Thread.sleep(( int )Math.random()* 300 );
             catch  (InterruptedException e) {
                 e.printStackTrace();
             }
             clerk.getProduct(); //从店员取走整数
         }
     }
     
}

例子3:购票窗口实现票数同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package  com.direct.demo;
 
import  java.util.concurrent.locks.Lock;
import  java.util.concurrent.locks.ReentrantLock;
 
public  class  ThreadTicket {
     public  static  void  main(String[] args) {
         Booking b1 =  new  Booking( "军人售票口" );
         Booking b2 =  new  Booking( "学生售票口" );
         Booking b3 =  new  Booking( "老年人售票口" );
         Booking b4 =  new  Booking( "网上售票口" );
         b1.start();
         b2.start();
         b3.start();
         b4.start();
     }
}
 
/*
  * 多窗口卖票系统。多线程
  * 票数为静态的,共享数据
  * synchronized(对象){}代码块中的内容是加锁的,
  * 即当一个线程在使用时,其他线程不可以进入。
  * 使得共享资源数据的安全。
  */
class  Booking  extends  Thread{
     public   Booking(String name){
         super (name);
     }  
     static   int  ticket =  50 ; //票数共50张
     Lock lock =  new  ReentrantLock(); //明锁

/*
* ReentrantLock根据传入构造方法的布尔型参数实例化出Sync的实现类FairSync和NonfairSync
* ,分别表示公平的Sync和非公平的Sync。
* 由于ReentrantLock我们用的比较多的是非公平锁

ReentrantLock 和synchronized 均为重入锁

* 1. ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。

2. ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

3. ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。

 对ReentrantLock的可重入锁这篇博客使用简单的例子进行讲解,  http://blog.csdn.net/yanyan19880509/article/details/52345422

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
      * Lock是个接口,只能实例化它的子类
      * 明锁适合高并发,上万
      * 暗锁适合并发率不高时,效率高
      */
     
     //重写run方法,
     public  void  run(){         
             while (ticket> 0 ){
                     synchronized  (Booking. class ) {
                         if  (ticket> 0 ) {
                             System.out.println( super .getName()+ "窗口---->卖出的车票号No." +ticket);
                             ticket--;
                         } else  {
                             System.out.println( super .getName()+ "票已售罄!!!" );
                         }              
                      try  {
                         sleep( 100 ); //睡100毫秒,抛出多线程异常
                     catch  (InterruptedException e) {
                         e.printStackTrace();
                     }
                }
                     /*lock.lock();//加锁,锁定以下代码
                     if (ticket>0) {
                         System.out.println(super.getName()+"卖票:"+ticket);
                         ticket--;
                     }else {
                         System.out.println(super.getName()+"票已售罄!!!");
                     }
                     try {
                         Thread.sleep(100);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     lock.unlock();//解锁
*/       }      
         
     }
}

例子4:线程中sleep()和wait()方法测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package  com.direct.demo;
 
public  class  TestSleepaWait {
     public  static  void  main(String[] args) {
         new  Thread( new  Thread1()).start();
         try  {
             Thread.sleep( 5000 );
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
         new  Thread( new  Thread2()).start();
     }
     
}
 
class  Thread1  implements  Runnable{
     public  void  run() {
         synchronized  (TestSleepaWait. class ) {
             System.out.println( "Thread1 is start........" );
             System.out.println( "Thread1 is wait.............." );
             try  {
                 //调用wait方法,线程会放弃对象锁,进入等待对象的等待锁定池
                 TestSleepaWait. class .wait();
             catch  (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println( "Thread1 is go on........" );
             System.out.println( "Thread1 is over!" );        
         }      
     }      
}
 
class  Thread2  implements  Runnable{
 
     @Override
     public  void  run() {
         synchronized  (TestSleepaWait. class ) {
             System.out.println( "Thread2 is enter.........." );
             System.out.println( "Thread2 is sleep......." );
             //只有针对对象调用notify()方法后本线程才进入对象锁定池
             //准备获取对象进入运行状态
             TestSleepaWait. class .notify();
             //===============
             //如果把上句注释掉。即对象锁调用了wait方法,但是没有调用notify
             //程序就一致处于挂起状态
             try  {
                 Thread.sleep( 5000 );
                 //sleep方法暂停执行时间,让出CPU,监控状态保持,
                 //时间到 了就回复运行, 不会释放对象锁
             catch  (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println( "Thread2 is going on.........." );
             System.out.println( "Thread2 is over!!!!" );
         }
         
     }
     
} 

例子5:sleep()实现对象存取值

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package  com.direct.demo;
 
public  class  ThreadCom {
     public  static  void  main(String[] args) {
         Person person =  new  Person();
           new  Thread( new  Producer(person)).start();
           new  Thread( new  Consumer(person)).start();
     }
 
}
 
class  Person{
     private  String name =  "张杰" ;
     private  String sex =  "男" ;
     public  synchronized  void  put(String name,String sex){
         this .name = name;
         this .sex = sex;
         try  {
             Thread.sleep( 100 );
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
     }
     //方法加锁
     public  synchronized  void  get(){
         System.out.println(name+ "----->" +sex);
         try  {
             Thread.sleep( 100 );
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
     }
}
 
class  Consumer  implements  Runnable{
     Person person;
     public  Consumer(Person person){
         this .person = person;
     }
     public  void  run() {
         while ( true ){
             person.get();
         }
     }
}
 
class   Producer  implements  Runnable{
     Person person;
     public  Producer(Person person){
         this .person = person;
     }
     public  void  run() {
         int  i =  0 ;
         while  ( true ) {
             if  (i== 0 ) {
                 person.put( "谢娜" "女" );
             } else  {
                 person.put( "张杰" "男" );
             }
             i = (i+ 1 )% 2 ; //奇数和偶数
         }
         
     }
     
}   

 

例子6:死锁发生条件

在写代码时要避免死锁

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package  com.direct.demo;
 
public  class  DeadLock {
     public  static  void  main(String[] args) {
         ThreadLock tl =  new  ThreadLock( true );
         ThreadLock tl2 =  new  ThreadLock( false );
         new  Thread(tl).start();
         new  Thread(tl2).start();
     }
}
 
/*
  * 死锁的产生条件:
  * 1、至少一个资源共享
  * 2、至少有一个线程(任务),必须持有资源,且等待获取别的线程持有的资源
  * 3、任务抢不到资源
  * 4、必须有无限循环
  * (1) 互斥条件:一个资源每次只能被一个进程使用。
  * (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  * (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
  * (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
  * 举例说明:不可剥夺资源A、B,进程C、D
  * 不可剥夺资源:一个进程申请了之后,不能强制收回,只能进程结束之后自动释放。内存是可剥夺资源
  * 进程C申请了资源A,进程D申请了资源B。
  * 接下来进程C的操作需要用到资源B,进程D的操作需要用到资源A
  * 但是C、D都得不到资源,就引发了死锁
  */
 
class  Lock{
     static  Object lockOne =  new  Object(); //资源A
     static  Object lockTwo =  new  Object(); //资源B
}
 
 
class  ThreadLock  implements  Runnable{
     private  boolean  flag;
     public  ThreadLock( boolean  flag){
         this .flag = flag;
     }
     @Override
     public  void  run() {
         if (flag){
             while  ( true ) {
                 synchronized  (Lock.lockOne) {
                     System.out.println( " this is lockOne" );
                     synchronized  (Lock.lockTwo) {
                         System.out.println( "this is lockTwo" );
                     }
                 }
             }
         } else  {
             while  ( true ) {
                 synchronized  (Lock.lockTwo) {
                     System.out.println( " 这是 lockTwo" );
                     synchronized  (Lock.lockOne) {
                         System.out.println( "这是 lockOne" );
                     }
                 }
             }
         }
     }
     
     
}

猜你喜欢

转载自blog.csdn.net/fct2001140269/article/details/79601174
今日推荐