多线程访问共享数方式的总结



1.多个线程访问共享数据的方式
多个线程访问共享数据分为两种方式:
1)每个线程执行操作共享数据的方式相同
2)每个线程执行操作共享数据的方式不同


2.多个线程执行操作共享数据的方式相同
如果每个线程执行操作共享数据的方式相同,那么可以使用同一个Runnable对象,将共享数据放在Runnable中并重写操作共享数据的run()方法。然后创建多个线程并将同一个Runnable对象作为参数传入线程的构造器中。例如售票系统。
//售票类
class Tickets implements Runnable {
	
	//定义总票数为100
	private int tickets = 100;
	
	//重写run方法,封装运行代码
	public void run() {
		//循环售票
		while(true) {
			//同步代码块,使用本类字节码对象作为锁
			synchronized(Tickets.class) {
				//如果票数大于0,则可以继续出售。每售出一张,票数减一
				if(tickets > 0) {
					System.out.println(Thread.currentThread().getName() + "售出第" + (tickets--) + "号票");
				}
			}
		}
	}	
}

public class TicketDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Tickets tickets = new Tickets();
		//创建四个售票窗口
		Thread t1 = new Thread(tickets);
		Thread t2 = new Thread(tickets);
		Thread t3 = new Thread(tickets);
		Thread t4 = new Thread(tickets);
		//开始售票
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}



3.多个线程执行操作共享数据的方式不同
如果每个线程执行操作共享数据的方式不同,可以有3中方式实现:
1)将共享数据封装在一个对象中,然后将此对象逐一传递给各个不同的Runnable,每个Runnable的run()封装不同操作共享数据的方法。
例:设计4个线程,其中2个线程每次对j加1,另外两个线程每次对j减1。
//定义Data类封装数据j
class Data {
	
	private int j = 0;
	
	//对j进行加1的操作,因为要设计多线程访问,所以是同步方法
	public synchronized void increment(){
		System.out.println("对j加1后j的值为:" + (++j));
	}
	
	//对j进行减1的操作
	public synchronized void decrement(){
		System.out.println("对j减1后j的值为:" + (--j));
	}
}

//定义MyRunnalbePlus对j进行加操作
class MyRunnalbePlus implements Runnable{
	
	private Data data;
	
	public MyRunnalbePlus(Data data){
		this.data = data;
	}
	@Override
	public void run() {
		while(true){
			data.increment();
		}
	}
}

//定义MyRunnalbeDec对j进行加操作
class MyRunnalbeDec implements Runnable{
	
	private Data data;
	
	public MyRunnalbeDec(Data data){
		this.data = data;
	}
	@Override
	public void run() {
		while(true){
			data.decrement();
		}
	}
}


public class MultiThreadShareData {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Data data = new Data();
		//将同一个data作为参数传入Runnable对象
		MyRunnalbePlus plus = new MyRunnalbePlus(data);
		MyRunnalbeDec dec = new MyRunnalbeDec(data);
		//分别开启两个加j和减j的线程
		for(int i = 0; i < 2; i++){
			new Thread(plus).start();
			new Thread(dec).start();
		}
	}

}

2)将不同操作共享数据的Runnable作为某一个类的内部类,共享数据作为外部类的成员变量。
public class MultiThreadShareData {
	
	//共享数据作为外部类成员变量
	private static int j = 0;
	

	//对j进行加1的操作,因为要设计多线程访问,所以是同步方法
	public static synchronized void increment(){
		System.out.println("对j加1后j的值为:" + (++j));
	}
	
	//对j进行减1的操作
	public static synchronized void decrement(){
		System.out.println("对j减1后j的值为:" + (--j));
	}
	
	//将Runnable定义为内部类
	static class Inc implements Runnable{
		@Override
		public void run() {
			while(true)
				increment();
		}
	}
	
	static class Dec implements Runnable{
		@Override
		public void run() {
			while(true)
				decrement();
		}
	}
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//创建不同的Runnable
		Inc inc = new Inc();
		Dec dec = new Dec();
		
		for(int i = 0; i < 2; i++){
			new Thread(inc).start();
			new Thread(dec).start();
		}
	}

}




3)上面两种方式的组合:将共享数据封装在一个对象中,每个线程对共享数据的操作也由该对象完成。对象作为外部类的成员变量,而Runnable定义为内部类。
//定义Data类封装数据j
class Data {
	
	private int j = 0;
	
	//对j进行加1的操作,因为要设计多线程访问,所以是同步方法
	public synchronized void increment(){
		System.out.println("对j加1后j的值为:" + (++j));
	}
	
	//对j进行减1的操作
	public synchronized void decrement(){
		System.out.println("对j减1后j的值为:" + (--j));
	}
}


public class MultiThreadShareData {

	//将共享数据作为类的成员变量
	private static Data data = new Data();
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//将不同操作共享数据的Runnable作为内部类。
		//此处为匿名内部类
		for(int i = 0; i < 2; i++){
			new Thread(new Runnable(){
				@Override
				public void run() {
					while(true)
						data.increment();
				}
			}).start();
			
			new Thread(new Runnable(){
				@Override
				public void run() {
					while(true)
						data.decrement();
				}
			}).start();
		}
	}

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值