多个线程之间共享数据的方式探讨
1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,卖票系统就可以这么做。
2.如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享:
(1)将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对该数据进行的各个操作的互斥和通信。
(2)将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。
实例1:将共享数据封装到一个对象中,逐一传给各个Runnable对象
public class ThreadTest2 {
static class ShareData{
private int j;
public synchronized void inc() {
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
}
public synchronized void dec() {
j--;
System.out.println(Thread.currentThread().getName() + "-dec:" + j);
}
}
static class MyRunnable1 implements Runnable{
public MyRunnable1(ShareData shareData) {
this.shareData = shareData;
}
ShareData shareData=new ShareData();
@Override
public void run() {
shareData.dec();
}
}
static class MyRunnable2 implements Runnable{
public MyRunnable2(ShareData shareData) {
this.shareData = shareData;
}
ShareData shareData=new ShareData();
@Override
public void run() {
shareData.inc();
}
}
public static void main(String args[]) {
final ShareData shareData=new ShareData();
//方式一:不完全面向对象
new Thread(new Runnable() {
@Override
public void run() {
shareData.inc();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
shareData.dec();
}
}).start();
//方式2:完全面向对象
new Thread(new MyRunnable1(shareData)).start();
new Thread(new MyRunnable2(shareData)).start();
}
}
实例2:将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,
public class ThreadTest1 {
private int j;
public static void main(String args[]) {
ThreadTest1 tt = new ThreadTest1();
Inc inc = tt.new Inc();
Dec dec = tt.new Dec();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(inc);
t.start();
t = new Thread(dec);
t.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 {
public void run() {
for (int i = 0; i < 100; i++) {
inc();
}
}
}
class Dec implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
dec();
}
}
}
}