多线程共享数据-示例

在 Java 传统线程机制中的共享数据方式,大致可以简单分两种情况:

多个线程行为一致,共同操作一个数据源: 

            也就是每个线程执行的代码相同,可以使用同一个 Runnable 对象,这个 Runnable 对象中有那个共享数据,例如,卖票系统就可以这么做。

多个线程行为不一致,共同操作一个数据源:

        也就是每个线程执行的代码不同,这时候需要用不同的Runnable 对象。例如,银行存取款

情况1:

    如果多个线程执行的代码相同的话就可以使用同一个Runnable,Runable中包含了共享的数据对象:

public class ThreadTest1 {
	public static void main(String[] args) {
		ShareData shareData = new ShareData();//共享的数据对象
		for (int i = 0; i < 4; i++) {
			new Thread(new RunnableCusToInc(shareData), "Thread " + i).start();
		}
	}
}

/**
 * 共享数据类
 **/
class ShareData {
	private int num = 10;

	public synchronized void inc() {
		num++;
		System.out.println(Thread.currentThread().getName()
				+ ": invoke inc method num =" + num);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

/**
 *多线程类
 **/
class RunnableCusToInc implements Runnable {
	private ShareData shareData;//共享的数据对象

	public RunnableCusToInc(ShareData data) {
		this.shareData = data;
	}
	
	public void run() {
		for (int i = 0; i < 5; i++) {
			shareData.inc();
		}
	}
}

情况2:

           不同线程操作同一共享对象,不同线程执行的代码也不相同.

        (1).将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个 Runnable 对象。每个线程对共享
数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信



package test.demo;

public class ThreadTest2 {
	public static void main(String[] args) {
		ShareData2 shareData = new ShareData2();
		for (int i = 0; i < 4; i++) {
			if (i % 2 == 0) {
				new Thread(new RunnableCusToInc2(shareData), "Thread " + i)
						.start();
			} else {
				new Thread(new RunnableCusToInc3(shareData), "Thread " + i)
						.start();
			}
		}
	}
}

/**
 * 共享数据类
 **/
class ShareData2 {
	private int num = 10;

	public synchronized void inc() {
		num++;
		System.out.println(Thread.currentThread().getName()
				+ ": invoke inc method num =" + num);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

/**
 * 多线程类
 **/
class RunnableCusToInc2 implements Runnable {
	private ShareData2 shareData;

	public RunnableCusToInc2(ShareData2 data) {
		this.shareData = data;
	}

	public void run() {
		for (int i = 0; i < 5; i++) {
			shareData.inc();
		}
	}
}

class RunnableCusToInc3 implements Runnable {
	private ShareData2 shareData;

	public RunnableCusToInc3(ShareData2 data) {
		this.shareData = data;
	}

	public void run() {
		for (int i = 0; i < 5; i++) {
			shareData.inc();
			System.out.println("33333333333333333333333");
		}
	}
}

(2).将这些 Runnable 对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对
共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个
Runnable 对象调用外部类的这些方法。


public class ThreadTest3 {
	public static void main(String[] args) {
		// 公共数据
		final ShareData shareData = new ShareData();
		for (int i = 0; i < 4; i++) {
			if (i % 2 == 0) {
				new Thread(new Runnable() {
					@Override
					public void run() {
						for (int i = 0; i < 5; i++) {
							shareData.inc();
						}
					}
				}, "Thread " + i).start();
			} else {
				new Thread(new Runnable() {
					@Override
					public void run() {
						for (int i = 0; i < 5; i++) {
							shareData.dec();
						}
					}
				}, "Thread " + i).start();
			}
		}
	}

	class ShareData {
		private int num = 10;

		public synchronized void inc() {
			num++;
			System.out.println(Thread.currentThread().getName()
					+ ": invoke inc method num =" + num);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		public synchronized void dec() {
			num--;
			System.err.println(Thread.currentThread().getName()
					+ ": invoke dec method num =" + num);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


猜你喜欢

转载自blog.csdn.net/lucca_Hello/article/details/80666425