zoukankan      html  css  js  c++  java
  • 线程系列6--多个线程之间共享数据的方式

    多线程共享数据的方式:

    1,如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,卖票系统就可以这么做。网上搜出来的东西都直接这样解说,包括传智播客中张孝祥也是这么讲的。但是我却迷茫了好久,为啥这个Runnable实现的多线程共享数据,在没有采取任何措施的情况下,没有出现执行混乱。当然网上没有找到我想要的答案。后来还是自己想明白了,虽然Runnable能实现数据对象共享,但是它并不能保证程序执行不混乱(自己代码测试)。大家可以试一下,可以在买票系统的方法中多加几行代码就会发现执行混乱问题。下面代码所示:

    public class ThreadSynchronized {
    	public static void main(String[] args) {
    		MyRunnable myRunnable = new MyRunnable();
    		new Thread(myRunnable,"窗口一").start();
    		new Thread(myRunnable,"窗口二").start();
    		new Thread(myRunnable,"窗口三").start();
    	}
    }
    
    class MyRunnable implements Runnable{
    	private int piao = 10;
    	@Override
    	public void run() {
    		while(piao > 0){
    			System.out.println("开始卖票");
    			piao--;
    			System.out.println(Thread.currentThread().getName()+"卖出票:"+piao);
    		}
    	}
    }

    结论:Runnable实现多线程数据共享,是不能保证线程互斥正常执行的,依然要采取措施才能保证,程序的正常执行顺序。

    
    

      

    2,如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,例如,设计4个线程。其中两个线程每次对j增加1,另外两个线程对j每次减1,银行存取款有两种方法来解决此类问题:将共享数据封装成另外一个对象,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对数据进行各个操作的互斥和通信;将Runnable对象作为一个类的内部类,共享数据作为这个类的成员变量,每个线程对共享数据的操作方法也封装在外部类,以便实现对数据的各个操作的同步和互斥,作为内部类的各个Runnable对象调用外部类的这些方法。

    public class MultiThreadShareData {
    
        public static void main(String[] args) {
    
            ShareData task = new ShareData(); //公共数据和任务放在task中
    
            for(int i = 0; i < 2; i ++) { //开启两个线程增加data
    
                new Thread(new Runnable() {
    
                    @Override
                    public void run() {
                        task.increment();
                    }
                }).start();
            }
    
            for(int i = 0; i < 2; i ++) { //开启两个线程减少data
    
                new Thread(new Runnable() {
    
                    @Override
                    public void run() {
                        task.decrement();
                    }
                }).start();
            }           
        }
    }   
    
    
    class ShareData /*implements Runnable*/ {
    
        private int data = 0;
        public synchronized void increment() { //增加data
            System.out.println(Thread.currentThread().getName() + ": before : " + data);
            data++;
            System.out.println(Thread.currentThread().getName() + ": after : " + data);
        }
    
        public synchronized void decrement() { //减少data
            System.out.println(Thread.currentThread().getName() + ": before : " + data);
            data--;
            System.out.println(Thread.currentThread().getName() + ": after : " + data);
        }
    }
    

    就如上面那个题目所描述的,两个线程执行data增,两个线程执行data减。针对这种情况,我们要实现两个Runnable了,因为很明显有两个不同的任务了,一个任务执行data增,另一个任务执行data减。为了便于维护,可以将两个任务方法放到一个类中,然后将data也放在这个类中,然后传到不同的Runnable中,即可完成数据的共享。

  • 相关阅读:
    无限维
    黎曼流形
    why we need virtual key word
    TOJ 4119 Split Equally
    TOJ 4003 Next Permutation
    TOJ 4002 Palindrome Generator
    TOJ 2749 Absent Substrings
    TOJ 2641 Gene
    TOJ 2861 Octal Fractions
    TOJ 4394 Rebuild Road
  • 原文地址:https://www.cnblogs.com/aoshicangqiong/p/7751681.html
Copyright © 2011-2022 走看看