多线程之间共享数据的方式探讨

多线程之间共享数据的方式探讨

方式一:代码一致

  • 如果每个线程执行的代码相同,可以用一个 Runnable 对象,这个 Runnable 对象中存放那个共享数据(卖票系统可以这样做)。
public class MultiThreadShareData {
    public static void main(String[] args) {
        MyShareData shareData=new MyShareData();
        //放入不同的线程中
        new Thread(shareData).start();

        new Thread(shareData).start();

    }
}

class MyShareData implements Runnable {
        // 共享的数据
        private int count = 100;

        @Override
        public void run() {
            while (count > 0) {
                synchronized (this) {
                    if (count > 0) {
                        count--;
                        System.out.println(Thread.currentThread().getName() + " 减了1,count还剩:" + count);
                    }

                }

            }
        }
    }

 

方式二:代码不一致

  • 如果每个线程执行的代码不同时,就需要不同的 Runnable 对象:

a. 将共享数据封装在一个对象中,然后将这个对象逐一传递给各个 Runnable 对象,每个线程对共享数据操作的方法也分配到这个对象中,这样容易实现针对该数据进行的各个操作的互斥通信。

public class MultiThreadShareData {

    private int shareData=0;

    public static void main(String[] args) {
        ShareData data = new ShareData();

        new Thread(new MyRunnable1(data)).start();

        new Thread(new MyRunnable2(data)).start();
    }

}

class MyRunnable1 implements Runnable{

    private ShareData data;

    public MyRunnable1(ShareData data){
        this.data=data;
    }

    @Override
    public void run() {
        for(int i=0;i<100;i++){
            //对数据进行增加
            this.data.increment();
        }
    }
}

class MyRunnable2 implements Runnable{

    private ShareData data;

    public MyRunnable2(ShareData data){
        this.data=data;
    }

    @Override
    public void run() {
        for(int i=0;i<100;i++){
            //对数据进行减少
            this.data.decrement();
        }
    }
}

/**
 将共享的数据封装成一个类
*/
class ShareData{
    //共享数据
    private int j=0;

    public synchronized void increment(){
        this.j++;
        System.out.println(Thread.currentThread().getName()+":j增加了1后j="+j);
    }

    public synchronized void decrement() {
        this.j--;
        System.out.println(Thread.currentThread().getName()+":j减少了1后j="+j);
    }
    public int getJ() {
        return j;
    }
}

b. 将 Runnable 对象作为某一个类的内部类,共享数据作为这个外部类的成员变量,每个线程对共享数据的操作方法也分配到外部类中,实现共享数据的互斥和通信操作,作为内部类的各个 Runnable 对象调用外部类的这些方法。

public class MultiThreadShareData {

    private int shareData=0;

    public static void main(String[] args) {
        MultiThreadShareData m=new MultiThreadShareData();
        //初始化Runnable对象
        MyRunnable1 myRunnable1 = m.new MyRunnable1();
        MyRunnable2 myRunnable2=m.new MyRunnable2();

        //开启线程
        new Thread(myRunnable1).start();

        new Thread(myRunnable2).start();
    }

    private synchronized void increment(){
        this.shareData++;
        System.out.println(Thread.currentThread().getName()+":shareData增加了1后shareData="+shareData);
    }

    private synchronized void decrement() {
        this.shareData--;
        System.out.println(Thread.currentThread().getName()+":shareData减少了1后shareData="+shareData);
    }

    /**
     * 作为内部类的Runnable对象
     */
    class MyRunnable1 implements Runnable{

        @Override
        public void run() {
            for(int i=0;i<100;i++){
                increment();
            }
        }
    }

    class MyRunnable2 implements Runnable{

        @Override
        public void run() {
            for(int i=0;i<100;i++){
                decrement();
            }
        }
    }
}

c. 以上两种方法的组合:将共享数据封装到一个对象中,每个线程对共享数据的操作方法也分配到对象中,对象作为外部类的成员变量或方法中的局部变量,每个线程的 Runnable 作为成员内部类或局部内部类。

 public class MultiThreadShareData {
   public static void main(String[] args) {

       ShareData data = new ShareData();

       new Thread(()->{
           for(int i=0;i<100;i++){
               data.increment();
           }
       }).start();

       new Thread(()->{
           for (int j=0;j<100;j++) {
               data.decrement();
           }
       }).start();
   }

}

/**
封装共享数据的对象
*/
class ShareData{
   //共享数据
   private int j=0;

   /**
    对共享数据进行操作的方法
   */
   public synchronized void increment(){
       this.j++;
       System.out.println(Thread.currentThread().getName()+":j增加了1后j="+j);
   }

   public synchronized void decrement() {
       this.j--;
       System.out.println(Thread.currentThread().getName()+":j减少了1后j="+j);
   }

   public int getJ() {
       return j;
   }
}

总之, 要同步互斥的几段代码最好放在几个独立的方法中,这些方法再放入一个类中,这样比较容易实现它们之间的同步互斥和通信。

你可能感兴趣的:(Java,多线程)