在 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(); } } } }