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

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

时间: 2024-10-06 06:45:51

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

多线程訪问共享数据(1)

多线程訪问共享数据解决方式: 一.什么是多线程 ?线程是程序中一个单一的顺序控制流程.在单个程序中同一时候运行多个线程完毕不同的工作,称为多线程. ?全部的线程尽管在微观上是串行运行的,可是在宏观上你全然能够觉得它们在并行运行 二.多线程訪问共享数据解决方式 1,假设每一个线程运行的代码同样,能够使用同一个Runnable对象,这个Runnable对象中有那个共享数据. 比如:卖票系统. 2,假设每一个线程运行的代码不同,这个时候须要用不同的Runnable对象,有例如以下三种方式来实现这些Ru

7.多个线程之间共享数据的方式探讨-JDK5多线程

1 /** 2 * 多个线程之间共享数据的方式探讨 3 * @author LiTaiQing 4 * 5 * ************************************************* 6 * 如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,有 7 * 如下两种方式来实现这些Runnble对象之间的数据共享: 8 * 1.将共享数据封装在另外一个对象中,然后将这个对象逐一传递给 9 * 各个Runnble对象.每个线程对共享数据的操作方法也分配到那个

多个Activity之间共享数据的方式

现在要做一个项目,多个Activity之间要共享数据,所以要考虑共享数据的方式. 其实有如下5种方式: 1.基于消息的通信机制  Intent ---bundle ,extra 数据类型有限,比如遇到不可序列化的数据Bitmap,InputStream, 或者LinkList链表等等数据类型就不太好用. 2. 利用static静态数据,public static成员变量: 3.基于外部存储的传输,  File/Preference/ Sqlite ,如果要针对第三方应用需要Content Pro

多线程访问共享对象和数据的方式

在多线程访问共享对象和数据时候大致可以分为两大类. 1:如果每个线程执行的代码相同,可以使用同一个runnable对象,这个runnable对象中有那个共享对象.如:买票系统. 1 public class MulteThreadlShareData { 2 public static void main(String[] args) { 3 ShareData shareData = new ShareData(); 4 new Thread(shareData).start(); 5 new

有关多线程与线程共享数据的简单实现

首先讨论一下一个简单直接的问题,为什么要学多线程? 那么原因很简单,会了多线程,你就能涨工资或者找到更好的工作啊!!! 开个玩笑. 好吧,其实不怎么好笑. 多线程能解决什么问题? 举个例子,现在有两个任务A,B在同时进行,A需要10s,B需要2s.没有多线程之前,通常的做法无非两种,先执行A再执行B,或者先执行B再执行A,时间上的结果都是需要12s.那么有没有可能,A和B同时进行呢?有的!用多线程来实现.这个时候,AB任务的完成时间就是10s,节约了2s. 接下来要讲实现了. 讲实现之前,区分一

Java多个线程之间处理共享数据的方式

题目要求: 有4个线程,其中两个线程每次对x加1,另外两个每次对x减1,如何实现? 分析: x就是这4个线程要处理的共享数据,不同种线程有不同的处理方式,但操作的数据是共同的,联想到"窗口买票问题",但是卖票只是单纯的减. 所以,多个线程访问共享对象或数据的方式,先看,如果每个线程执行的代码相同,那么就可以使用同一个Runnable对象,这个对象中有被共享的数据,如买票问题. 如果每个线程执行的代码不同,肯定需要不用的Runnable对象,有两种方式实现这些不同的Runnable对象之

java多线程学习-多个线程访问对象共享数据的方式

public class MulitThreadShareData { public static void main(String[] args) { final ShareData1 data1 = new ShareData1(); new Thread(new Runnable() { public void run() { data1.increment(); } }).start(); new Thread(new Runnable() { public void run() { d

JAVA 并发编程-多个线程之间共享数据(六)

多线程共享数据的方式: 1,如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,卖票系统就可以这么做. 2,如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,例如,设计4个线程.其中两个线程每次对j增加1,另外两个线程对j每次减1,银行存取款 有两种方法来解决此类问题: 将共享数据封装成另外一个对象,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对

android五种数据存储方式

在Android中提供了如下五种数据存储方式: SharedPreferences 文件存储 SQLite数据库方式 内容提供器(ContentProvider) 网络存储 下面具体介绍一下这五种数据存储方式的用法. 1. SharedPreferences SharedPreferences是android平台上的一个轻量级存储类,主要保存一些常用的配置信息.可以保存long.int.String类型数据. SharedPreferences以键值对方式读取和存入,最终会以XML方式保存数据,