JAVA 并发编程-多个线程之间共享数据
原文地址:http://blog.csdn.net/hejingyuan6/article/details/47053409#
多线程共享数据的方式:
1,如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,卖票系统就可以这么做。
2,如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,例如,设计4个线程。其中两个线程每次对j增加1,另外两个线程对j每次减1,银行存取款
有两种方法来解决此类问题:
将共享数据封装成另外一个对象,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对数据进行各个操作的互斥和通信
将Runnable对象作为一个类的内部类,共享数据作为这个类的成员变量,每个线程对共享数据的操作方法也封装在外部类,以便实现对数据的各个操作的同步和互斥,作为内部类的各个Runnable对象调用外部类的这些方法。
每个线程执行的代码相同,可以使用同一个Runnable对象
卖票系统demo:
package com.xujishou;
public class SellTicket {
    /**
     * @param args
     */
    public static void main(String[] args) {
        Ticket t = new Ticket();
        new Thread(t).start();
        new Thread(t).start();
    }
}
class Ticket implements Runnable {
    private int ticket = 10;
    public void run() {
        while (ticket > 0) {
            ticket--;
            System.out.println("当前票数为:" + ticket);
        }
    }
}
执行

简单的多线程间数据共享,每个线程执行的代码不同,用不同的Runnable对象
设计4个线程。
其中两个线程每次对j增加1,另外两个线程对j每次减1
package com.xujishou;
public class TestThread {
    /**
     * @param args
     */
    public static void main(String[] args) {
        final MyData data = new MyData();
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                public void run() {
                    data.add();
                }
            }).start();
            new Thread(new Runnable() {
                public void run() {
                    data.dec();
                }
            }).start();
        }
    }
}
class MyData {
    private int j = 0;
    public synchronized void add() {
        j++;
        System.out.println("线程" + Thread.currentThread().getName() + "j为:" + j);
    }
    public synchronized void dec() {
        j--;
        System.out.println("线程" + Thread.currentThread().getName() + "j为:" + j);
    }
}

银行存取款实例:
package com.xujishou;
public class Acount {
    private int money;
    public Acount(int money) {
        this.money = money;
    }
    public synchronized void getMoney(int money) {
        // 注意这个地方必须用while循环,因为即便再存入钱也有可能比取的要少
        while (this.money < money) {
            System.out.println("取款:" + money + " 余额:" + this.money
                    + " 余额不足,正在等待存款......");
            try {
                wait();
            } catch (Exception e) {
            }
        }
        this.money = this.money - money;
        System.out.println("取出:" + money + " 还剩余:" + this.money);
    }
    public synchronized void setMoney(int money) {
        try {
            Thread.sleep(10);
        } catch (Exception e) {
        }
        this.money = this.money + money;
        System.out.println("新存入:" + money + " 共计:" + this.money);
        notify();
    }
    public static void main(String args[]) {
        Acount Acount = new Acount(0);
        Bank b = new Bank(Acount);
        Consumer c = new Consumer(Acount);
        new Thread(b).start();
        new Thread(c).start();
    }
}
// 存款类
class Bank implements Runnable {
    Acount Acount;
    public Bank(Acount Acount) {
        this.Acount = Acount;
    }
    public void run() {
        while (true) {
            int temp = (int) (Math.random() * 1000);
            Acount.setMoney(temp);
        }
    }
}
// 取款类
class Consumer implements Runnable {
    Acount Acount;
    public Consumer(Acount Acount) {
        this.Acount = Acount;
    }
    public void run() {
        while (true) {
            int temp = (int) (Math.random() * 1000);
            Acount.getMoney(temp);
        }
    }
}

总结:
其实多线程间的共享数据最主要的还是互斥,多个线程共享一个变量,针对变量的操作实现原子性即可。
原文地址:http://blog.csdn.net/hejingyuan6/article/details/47053409#
多线程共享数据的方式:
1,如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,卖票系统就可以这么做。
2,如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,例如,设计4个线程。其中两个线程每次对j增加1,另外两个线程对j每次减1,银行存取款
有两种方法来解决此类问题:
将共享数据封装成另外一个对象,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对数据进行各个操作的互斥和通信
将Runnable对象作为一个类的内部类,共享数据作为这个类的成员变量,每个线程对共享数据的操作方法也封装在外部类,以便实现对数据的各个操作的同步和互斥,作为内部类的各个Runnable对象调用外部类的这些方法。
下面逐一介绍
每个线程执行的代码相同,可以使用同一个Runnable对象
卖票系统demo:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | packagecom.xujishou;public classSellTicket {    /**     * @param args     */    public staticvoid main(String[] args) {        Ticket t = newTicket();        newThread(t).start();        newThread(t).start();    }}classTicket implementsRunnable {    privateint ticket = 10;    public void run() {        while(ticket > 0) {            ticket--;            System.out.println("当前票数为:"+ ticket);        }    }} | 
执行

简单的多线程间数据共享,每个线程执行的代码不同,用不同的Runnable对象
设计4个线程。
其中两个线程每次对j增加1,另外两个线程对j每次减1
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | packagecom.xujishou;public classTestThread {    /**     * @param args     */    public staticvoid main(String[] args) {        final MyData data = newMyData();        for(int i = 0; i < 10; i++) {            newThread(newRunnable() {                public void run() {                    data.add();                }            }).start();            newThread(newRunnable() {                public void run() {                    data.dec();                }            }).start();        }    }}classMyData {    privateint j = 0;    public synchronized void add() {        j++;        System.out.println("线程"+ Thread.currentThread().getName() + "j为:"+ j);    }    public synchronized void dec() {        j--;        System.out.println("线程"+ Thread.currentThread().getName() + "j为:"+ j);    }} | 

银行存取款实例:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | packagecom.xujishou;public classAcount {    privateint money;    public Acount(int money) {        this.money = money;    }    public synchronized void getMoney(int money) {        // 注意这个地方必须用while循环,因为即便再存入钱也有可能比取的要少        while(this.money < money) {            System.out.println("取款:"+ money + " 余额:"+ this.money                    + " 余额不足,正在等待存款......");            try{                wait();            } catch(Exception e) {            }        }        this.money = this.money - money;        System.out.println("取出:"+ money + " 还剩余:"+ this.money);    }    public synchronized void setMoney(int money) {        try{            Thread.sleep(10);        } catch(Exception e) {        }        this.money = this.money + money;        System.out.println("新存入:"+ money + " 共计:"+ this.money);        notify();    }    public staticvoid main(String args[]) {        Acount Acount = newAcount(0);        Bank b = newBank(Acount);        Consumer c = newConsumer(Acount);        newThread(b).start();        newThread(c).start();    }}// 存款类classBank implementsRunnable {    Acount Acount;    public Bank(Acount Acount) {        this.Acount = Acount;    }    public void run() {        while(true) {            int temp = (int) (Math.random() * 1000);            Acount.setMoney(temp);        }    }}// 取款类classConsumer implementsRunnable {    Acount Acount;    public Consumer(Acount Acount) {        this.Acount = Acount;    }    public void run() {        while(true) {            int temp = (int) (Math.random() * 1000);            Acount.getMoney(temp);        }    }} | 

总结:
其实多线程间的共享数据最主要的还是互斥,多个线程共享一个变量,针对变量的操作实现原子性即可。
JAVA 并发编程-多个线程之间共享数据的更多相关文章
- JAVA 并发编程-多个线程之间共享数据(六)
		多线程共享数据的方式: 1.假设每一个线程运行的代码同样.能够使用同一个Runnable对象,这个Runnable对象中有那个共享数据,比如,卖票系统就能够这么做. 2,假设每一个线程运行的代码不同. ... 
- 【转】JAVA 并发编程-多个线程之间共享数据
		原文地址:http://blog.csdn.net/hejingyuan6/article/details/47053409# 多线程共享数据的方式: 1,如果每个线程执行的代码相同,可以使用同一个R ... 
- Java并发编程--6.Exchanger线程间交换数据
		在两个线程之间定义同步点,当两个线程都到达同步点时,他们交换数据结构,因此第一个线程的数据结构进入到第二个线程中,第二个线程的数据结构进入到第一个线程中 在生产者-消费者情境模式中它包含了一个数缓冲区 ... 
- Java并发编程系列-(2) 线程的并发工具类
		2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ... 
- 【Java并发编程一】线程安全和共享对象
		一.什么是线程安全 当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用代码代码不必作其他的协调,这个类的行为仍然是正确的,那么称这个类是线程安全的 ... 
- Java并发编程实战 之 对象的共享
		上一篇介绍了如何通过同步多个线程避免同一时刻访问相同数据,本篇介绍如何共享和发布对象,使它们被安全地由多个进程访问. 1.可见性 通常,我们无法保证执行读操作的线程能看到其他线程写入的值,因为每个线程 ... 
- 【java并发编程实战】-----线程基本概念
		学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习 ... 
- Java并发编程扩展(线程通信、线程池)
		之前我说过,实现多线程的方式有4种,但是之前的文章中,我只介绍了两种,那么下面这两种,可以了解了解,不懂没关系. 之前的文章-->Java并发编程之多线程 使用ExecutorService.C ... 
- Java并发编程:进程和线程的由来(转)
		Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ... 
随机推荐
- js加载超时  nginx静态资源
			server { listen ; server_name www.example.com; client_max_body_size 20M; root /xxx/xxx;//项目路径 locati ... 
- android textview空格占位符以及一些其他占位符汇总
			== 普通的英文半角空格 == == == no-break space (普通的英文半角空格但不换行) == 中文全角空格 (一个中文宽度) == == en空格 (半个中文 ... 
- crontab定时任务_net
			2017年2月25日, 星期六 crontab定时任务 19. crontab 定时任务 通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本.时间间隔 ... 
- c++ 前置++与后置++的区别
			用C++编程的都知道,C++提供了一个非常强大的操作符重载机制,利用操作符重载,我们可以为我们自定义的类增加更多非常有用的功能.不过,C++也有限制,就是当我们为自定义的类重载操作符时,重载操作符的含 ... 
- CSS3实战之box-shadow篇
			box-shadow属性包含6个参数值:阴影类型.X轴位移.Y轴位移.阴影大小.阴影扩展和阴影颜色.这6个参数值可以有选择地省略. 现在我们用一个img元素来举栗子 我们先来写最简单的box-shad ... 
- pandas 视频讲座 from youtube
			Stephen Simmons - Pandas from the inside - YouTube https://www.youtube.com/watch?v=Dr3Hv7aUkmU 2016年 ... 
- Redis实战(一)CentOS 7上搭建redis-3.0.2
			1.安装redis wget http://download.redis.io/releases/redis-3.0.2.tar.gz tar zxvf redis-3.0.2.tar.gz cd ... 
- [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)
			[CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ... 
- linux服务-ssh
			任务目标:ssh登录,scp上传.下载,ssh秘钥登录, 修改ssh server端的端口为8888然后进行登录和scp测试 使用ssh登陆host1 使用scp下载文件 scp root@192.1 ... 
- Groovy/Spock 测试导论
			Groovy/Spock 测试导论 原文 http://java.dzone.com/articles/intro-so-groovyspock-testing 翻译 hxfirefox 测试对于软件 ... 
