java多线程实现数据共享

练习题:卖100个苹果,实现数据共享。

新建一个线程有两种方式:1.继承Thread类;2.是实现Runnable的方式:

那我们就先使用第一种方式来实现:

使用Thread实现数据的共享

第一步:

写一个了ShareThread继承Thread,并在ShareThread定义一个静态的Apple_Counts变量(注意:Apple_Counts因为是静态的,所以是共享数据)

    /**
     * 存在数据共享
     * @author liujun
     *
     */
    class ShareThread extends Thread{
        private static int Apple_Counts=100;//共享数据-苹果个数
        @Override
        public void run() {
            while(Apple_Counts>0){
                    if (Apple_Counts>0) {
                        try {
                            Thread.sleep(10);
                            System.out.println(Thread.currentThread().getName()+"卖了一个苹果,还剩"+--Apple_Counts);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
            }
        }
    }

在main方法开始三个线程:

    ShareThread mShareThread1=new ShareThread();
    ShareThread mShareThread2=new ShareThread();
    ShareThread mShareThread3=new ShareThread();
    mShareThread1.start();
    mShareThread2.start();
    mShareThread3.start();

执行的结果:

Thread-0卖了一个苹果,还剩99
Thread-1卖了一个苹果,还剩98
Thread-2卖了一个苹果,还剩99
Thread-0卖了一个苹果,还剩97//这里数据出现有错,因为上面的线程里没有使用同步锁
Thread-1卖了一个苹果,还剩97
........................
........................
Thread-0卖了一个苹果,还剩2
Thread-2卖了一个苹果,还剩1
Thread-1卖了一个苹果,还剩0
Thread-0卖了一个苹果,还剩-1 //这里数据出现有错,因为上面的线程里没有使用同步锁
Thread-2卖了一个苹果,还剩-2
第二步:

给ShareThread中添加同步代码块:

    /**
     * 存在数据共享
     * @author liujun
     *
     */
    class ShareThread extends Thread{
        private static int Apple_Counts=100;//共享数据-苹果个数
        @Override
        public void run() {
            while(Apple_Counts>0){
                //注意这里添加了同步代码块,同步锁对象是this
                synchronized (this) {
                    if (Apple_Counts>0) {
                        try {
                            Thread.sleep(10);
                            System.out.println(Thread.currentThread().getName()+"卖了一个苹果,还剩"+--Apple_Counts);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

再次执行main方法打印的结果:

Thread-2卖了一个苹果,还剩98
Thread-1卖了一个苹果,还剩99
Thread-0卖了一个苹果,还剩97
Thread-1卖了一个苹果,还剩96
Thread-0卖了一个苹果,还剩95
........................
........................
Thread-0卖了一个苹果,还剩1
Thread-1卖了一个苹果,还剩0
Thread-2卖了一个苹果,还剩0 //这里数据出现有错,都使用同步锁了?为什么????????
Thread-0卖了一个苹果,还剩-1 
第三步:

分析代码:

多线程在使用synchronized的时候,多个线程使用的锁对象必须是同一个。

    ShareThread mShareThread1=new ShareThread();
    ShareThread mShareThread2=new ShareThread();
    ShareThread mShareThread3=new ShareThread();

上面这三行代码new了三个对象,那么上面使用的同步锁是this;那上面的多线程在使用synchronized的时候,多个线程使用的锁对象(this)不是同一个,它们是分别为mShareThread1,mShareThread2,mShareThread3。所以上面虽然使用了synchronized还是会出现数据有错。

第四步:

修改代码:

保证使多线程在使用synchronized的时候,多个线程使用的锁对象是同一个就行,下面使用了的同步锁对象是:ShareThread.class。

    /**
     * 存在数据共享
     * @author liujun
     *
     */
    class ShareThread extends Thread{
        private static int Apple_Counts=100;//共享数据-苹果个数
        @Override
        public void run() {
            while(Apple_Counts>0){
                //注意这里添加了同步代码块,同步锁对象是ShareThread.class
                synchronized (ShareThread.class) {
                    if (Apple_Counts>0) {
                        try {
                            Thread.sleep(10);
                            System.out.println(Thread.currentThread().getName()+"卖了一个苹果,还剩"+--Apple_Counts);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

再次执行main方法打印的结果正常:

Thread-2卖了一个苹果,还剩98
Thread-1卖了一个苹果,还剩99
Thread-0卖了一个苹果,还剩97
Thread-1卖了一个苹果,还剩96
Thread-0卖了一个苹果,还剩95
........................
........................
Thread-0卖了一个苹果,还剩1
Thread-1卖了一个苹果,还剩0

总结:

1.上面通过继承Thread类的方式已经实现数据共享,但是一般我们不定义静态的变量作为数据共享,因为静态的生命周期比较长。

2.建议实现数据共享时使用实现runnable来实现。

使用Runnable实现数据的共享

第一步:

写一个了ShareRunable实现Runnable,并在ShareRunable定义一个Apple_Counts变量(注意:Apple_Counts是共享数据)


    /**
     * 存在数据共享
     * @author liujun
     *
     */
    class ShareRunable implements Runnable{

        private int Apple_Counts=100;//Apple_Counts就是共享数据

        @Override
        public void run() {
            while(Apple_Counts>0){
                if(Apple_Counts>0){
                    try {
                        Thread.sleep(10);
                        System.out.println(Thread.currentThread().getName()+"卖了一个苹果,还剩"+--Apple_Counts);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

在main方法开始三个线程:

    ShareRunable mMyRunables=new ShareRunable();
    new Thread(mMyRunables).start();
    new Thread(mMyRunables).start();
    new Thread(mMyRunables).start();

执行的结果:

Thread-0卖了一个苹果,还剩99
Thread-1卖了一个苹果,还剩98
Thread-2卖了一个苹果,还剩99
........................
........................
Thread-0卖了一个苹果,还剩2
Thread-2卖了一个苹果,还剩1
Thread-1卖了一个苹果,还剩0
Thread-0卖了一个苹果,还剩-1 //这里数据出现有错,因为上面的线程里没有使用同步锁
Thread-2卖了一个苹果,还剩-2
第二步:

给ShareRunable中添加同步代码块:

    /**
     * 存在数据共享
     * @author liujun
     *
     */
    class ShareRunable implements Runnable{

        private int Apple_Counts=100;//Apple_Counts就是共享数据

        @Override
        public void run() {
            while(Apple_Counts>0){
            //注意这里添加了同步代码块,同步锁对象是this或者是ShareThread.class
                synchronized (this) {
                if(Apple_Counts>0){
                    try {
                        Thread.sleep(10);
                        System.out.println(Thread.currentThread().getName()+"卖了一个苹果,还剩"+--Apple_Counts);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
               }    
            }
        }
    }

再次执行main方法打印的结果正常:

Thread-2卖了一个苹果,还剩99
Thread-1卖了一个苹果,还剩98
Thread-0卖了一个苹果,还剩97
Thread-1卖了一个苹果,还剩96
Thread-0卖了一个苹果,还剩95
........................
........................
Thread-0卖了一个苹果,还剩1
Thread-1卖了一个苹果,还剩0

总结:

1.上面通过实现Runable类的方式已经实现数据共享

2.建议实现数据共享时使用实现runnable来实现。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值