码迷,mamicode.com
首页 > 编程语言 > 详细

多线程06-多线程共享数据的方式(经验小结)

时间:2014-06-14 22:20:08      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   code   tar   color   

     1.案例分析-01

      通过代码实现火车票出售的例子

      在实现代码之前先对问题进行分析:火车票出售应该是在多个窗口进行的(即多个线程),以一个车的班次来说,该班次的火车票张数即为多个窗口共享的数据

即这份共享数据为出售特定班次的火车票,这个动作在多个窗口都是不变的,变更的只有火车票的剩余张数.代码实现如下:

package org.lkl.thead;

/**
 * 
 * Function : 多线程共享数据
 * 
 * @author : Liaokailin CreateDate : 2014-6-13 version : 1.0
 */
public class MultiThreadShareData {
    public static void main(String[] args) {
        SellTicket s = new SellTicket(); // 共享对象
        new Thread(s, "1").start();
        new Thread(s, "2").start();
        new Thread(s, "3").start();
        new Thread(s, "4").start();
        new Thread(s, "5").start();
    }

}

/**
 * 出售火车票  
 */
class SellTicket implements Runnable {
    private int ticket = 100;

    @Override
    public void run() {

        while (true) {
            synchronized (SellTicket.class) {
            if (ticket > 0) {
            
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    ticket-- ;
                    System.out.println("窗口" + Thread.currentThread().getName()
                            + "出售合肥到北京火车票剩余车票" + ticket);
                }else{
                    break ;
                }
            }
        }

    }
}

 

   通过上面的代码可以发现,多线程共享的数据是卖火车票,而这个动作在各个线程中都是不变的,因此可以做如下的小结:

   多线程中各个线程执行的代码相同,那么可以使用同一个Runnable对象来实现共享数据。

      2. 案例分析-02

         和上面问题乡对应的是 如果多个线程中执行的代码不同呢? 该如何去处理数据之间的共享?

         例如: 

               设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1 。

          通过问题可以发现,线程中执行的代码显示是不同的,一个是j++ 一个是j--,在前面我们说过 要同步互斥的代码或者算法应该分别放在独立的方法中,并且这些方法都放在同一个类中,这样子

比较容易实现他们之间的同步互斥和通信

          那么可以设计如下的业务类: 

class Business{
    private int j = 0;
    
    public synchronized void increment(){
        j++ ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }
    public synchronized void decrement(){
        j-- ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }
}

 

     要实现多个线程的不同操作,可以将不同的操作防止在不同的Runnable中 然后将不同的Runnable对象传递给不同的线程

        

package org.lkl.thead;


/**
 *   设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1 
 */
public class ShareDataFoo {
    public static void main(String[] args) {
        Business b = new Business() ;
        for(int i= 0 ;i<2;i++){
            new Thread(new OperatorFoo01(b)).start();
            new Thread(new OperatorFoo02(b)).start();
            
        }
        
    }

    
}
class OperatorFoo01 implements Runnable{
    private Business business;
    public OperatorFoo01(Business business){
        this.business = business ;
    }
    @Override
    public void run() {
        business.increment() ;
    }
}

class OperatorFoo02 implements Runnable{
    private Business business;
    public OperatorFoo02(Business business){
        this.business = business ;
    }
    @Override
    public void run() {
        business.decrement() ;
    }
}

class Business{
    private int j = 0;
    
    public synchronized void increment(){
        j++ ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }
    public synchronized void decrement(){
        j-- ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }
}

 

       运行代码得到的结果: 

Thread-0,j=1
Thread-1,j=0
Thread-2,j=1
Thread-3,j=0

 

 

我们可以做个小结:

   如果每个线程执行的代码不同,这时候需要不同的Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享

      1.将共享数据封在在一个对象中,然后将这个对象逐一传递给各个不同Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥

和通行 (上面我们的例子就是采用这样的方式)

      2.将这些Runnable对象作为某个类的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作也分配给外部类,以便对共享数据进行的各个操作的互斥和通信,作为内部类的各个

Runnable对象调用外部类的这些方法

      对于第二点同样以上面的例子得到如下代码:

package org.lkl.thead;


/**
 *   设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1 
 */
public class ShareDataFoo2 {
    public static void main(String[] args) {
        ShareDataFoo2 foo = new ShareDataFoo2() ;
        
        for(int i= 0 ;i<2;i++){
            new Thread(foo.new OperAdd()).start();
            new Thread(foo.new OperSub()).start();
            
        }
        
    }
    
    private int j = 0 ;
    
    public synchronized  void increment(){
        j++ ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }
    
    public synchronized void decrement(){
        j-- ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }

     class OperAdd implements Runnable{
        @Override
        public void run() {
            increment() ;
        }
    }
    
     class OperSub implements Runnable{
        @Override
        public void run() {
            decrement() ;
        }
    }
    
    
}

 

      也可以对上面的两种方法进行组合:

     将共享数据封装到另外一个对象中,每个线程对共享数据的操作方法也分配到那个对象本身上来完成,该对象作为这个外部类中的成员变量或者方法中的局部变量,每个线程的Runnable对象

作为外部类中的成员内部类或局部内部类,如下面代码:

  

package org.lkl.thead;


/**
 *   设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1 
 */
public class ShareDataFoo3 {
    public static void main(String[] args) {
        ShareDataFoo3 foo = new ShareDataFoo3() ;
        for(int i= 0 ;i<2;i++){
            new Thread(foo.new OperatorFoo01()).start();
            new Thread(foo.new OperatorFoo02()).start();
            
        }
        
    }

    private Business2 business = new Business2() ;
    class OperatorFoo01 implements Runnable{
     
        @Override
        public void run() {
            business.increment() ;
        }
    }

    class OperatorFoo02 implements Runnable{
        @Override
        public void run() {
            business.decrement() ;
        }
    }
    
    
}


class Business2{
    private int j = 0;
    
    public synchronized void increment(){
        j++ ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }
    public synchronized void decrement(){
        j-- ;
        System.out.println(Thread.currentThread().getName()+",j="+j);
    }
}

 

 

 

 

 

 

 

 

多线程06-多线程共享数据的方式(经验小结),布布扣,bubuko.com

多线程06-多线程共享数据的方式(经验小结)

标签:style   class   blog   code   tar   color   

原文地址:http://www.cnblogs.com/liaokailin/p/3786320.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!