多线程之3-------多个线程访问共享数据的方式

本文先从一个面试题说起:

设计4个线程,其中两个线程每次对 j +1, 另外两个线程对 j-1,

分析: 这里 j 看作是一个共享数据

从现实例子来看,可以扩展到卖票,假设有100张票, 分5个窗口卖。这个问题也涉及到多线程

解决:

分两种情况

1 如果每个线程执行的代码相同,可以使用同一个Runnable 对象,此Runnable 对象存在共享数据, 如: 卖票程序可以这么做,因为都是执行减少的过程

代码

public class MultiThreadShareData {

public static void main(String[] args) {
ShareData1 data1 = new ShareData1();
new Thread(data1).start();
new Thread(data1).start();
}

class ShareData1 implements Runnable {
private int count = 100;
@Override
public void run() {
while(true){
count--;
}

}

}

注意这里只用了data1 这一个Runnable 对象

2 每个线程执行的代码不同,就需要用不同的Runnable 对象,有两种方式来实现这些Runnable 对象之间的数据共享。

第一种: 将共享数据封装在另外一个对象中,然后将这个对象逐一传递给每个Runnable 对象,每个线程对共享数据的操作方法也分配到那个对象去完成,

代码如下,注意 data1 对象为共享数据

public class MultiThreadShareData {
public static void main(String[] args) {
ShareData1 data1 = new ShareData1();
new Thread(new MyRunnable1(data1)).start();
new Thread(new MyRunnable2(data1)).start();
}

}
class MyRunnable1 implements Runnable{
private ShareData1 data1;
public MyRunnable1(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.decrement();
}
}
class MyRunnable2 implements Runnable{
private ShareData1 data1;
public MyRunnable2(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.increment();
}
}

class ShareData1{
private int j = 0;
public synchronized void increment(){
j++;
}

public synchronized void decrement(){
j--;
}
}

第二种 将这些Runnable 对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,

以便实现对共享数据进行的各个操作的互斥与通信, 作为内部类的每个Runnable 对象调用外部类的这些方法.

代码如下:

public class MultiThreadShareData {
public static void main(String[] args) {
ShareData1 data2 = new ShareData1();
new Thread(new MyRunnable1(data2)).start();
new Thread(new MyRunnable2(data2)).start();

final ShareData1 data1 = new ShareData1();
new Thread(new Runnable(){
@Override
public void run() {
data1.decrement();
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
data1.increment();
}
}).start();
}
}
class MyRunnable1 implements Runnable{
private ShareData1 data1;
public MyRunnable1(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.decrement();
}
}
class MyRunnable2 implements Runnable{
private ShareData1 data1;
public MyRunnable2(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.increment();
}
}

class ShareData1{
private int j = 0;
public synchronized void increment(){
j++;
}
public synchronized void decrement(){
j--;
}
}

一个内部类,如果放在static 方法里,不能访问全局变量, 要访问需要将变量用static 修饰,或者是将变量改为局部变量,用final 修饰

现在回到刚开始的问题, 代码如下:

public class ShareDataTest {
int j = 0;
public static void main(String args[]){
ShareDataTest t = new ShareDataTest();
Inc inc = t.new Inc();
Dec dec = t.new Dec();

/**
* 这里循环表示依次启动两次,每次启动两个线程,
* 一个增加的线程,一个减少的线程
* 这里 对j的增减没有考虑先后顺序
*/
for(int i=0;i<2;i++){
Thread th = new Thread(inc);
th.start();
th = new Thread(dec);
th.start();
}
}
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+" inc: "+j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+" dec: "+j);
}
class Inc implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
dec();
}
}
}
}

运行效果如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值