风也温柔

计算机科学知识库

java多线程数据同步-java多线程实现数据共享

  练习题:卖100个苹果java多线程数据同步,实现数据共享。

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

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

  使用实现数据的共享 第一步:

  写一个了继承java多线程数据同步,并在定义一个静态的变量(注意:因为是静态的java多线程数据同步-java多线程实现数据共享,所以是共享数据)

  <pre class="prettyprint">` /**

 * 存在数据共享
 * @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();
                    }
                }
        }
    }
}`</pre>

  在main方法开始三个线程:

  <pre class="prettyprint">` ShareThread mShareThread1=new ShareThread();

ShareThread mShareThread2=new ShareThread();
ShareThread mShareThread3=new ShareThread();
mShareThread1.start();
mShareThread2.start();
mShareThread3.start();`</pre>

  执行的结果:

   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

  第二步:

  给中添加同步代码块:

  <pre class="prettyprint">` /**

 * 存在数据共享
 * @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();
                    }
                }
            }
        }
    }
}`</pre>

  再次执行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 

  第三步:

  分析代码:

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

  <pre class="prettyprint">` ShareThread mShareThread1=new ShareThread();

ShareThread mShareThread2=new ShareThread();
ShareThread mShareThread3=new ShareThread();`</pre>

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

  第四步:

  修改代码:

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

  <pre class="prettyprint">` /**

 * 存在数据共享
 * @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();
                    }
                }
            }
        }
    }
}`</pre>

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

   Thread-2卖了一个苹果,还剩98

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

  总结:

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

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

  使用实现数据的共享 第一步:

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

  <pre class="prettyprint">`

/**
 * 存在数据共享
 * @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();
                }
            }
        }
    }
}`</pre>

  在main方法开始三个线程:

  <pre class="prettyprint">` ShareRunable mMyRunables=new ShareRunable();

new Thread(mMyRunables).start();
new Thread(mMyRunables).start();
new Thread(mMyRunables).start();`</pre>

  执行的结果:

   Thread-0卖了一个苹果,还剩99

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

  第二步:

  给中添加同步代码块:

  <pre class="prettyprint">` /**

 * 存在数据共享
 * @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();
                }
            }
           }    
        }
    }
}`</pre>

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

   Thread-2卖了一个苹果,还剩99

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

  总结:

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

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

  文章来源:https://blog.csdn.net/u012987546/article/details/52140164