如下图,多个线程访问共享数据:
编码应该如何实现?
举一个多线程访问共享数据的例子:设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1(类似于多个窗口卖火车票)。
- public class MultiThreadShareData {
- private static ShareData1 data1 = new ShareData1();
- public static void main(String[] args) {
- ShareData1 data2 = new ShareData1();
- new Thread(new MyRunnable1(data2)).start();//线程1
- new Thread(new MyRunnable2(data2)).start();//线程2,方法二
- 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{//负责减的Runnable
- private ShareData1 data1;
- public MyRunnable1(ShareData1 data1){
- this.data1 = data1;
- }
- public void run() {
- while(true){
data1.decrement();
- }
- }
- }
- class MyRunnable2 implements Runnable{//负责加的Runnable
- private ShareData1 data1;
- public MyRunnable2(ShareData1 data1){
- this.data1 = data1;
- }
- public void run() {
- while(true){
data1.increment();
- }
- }
- }
- class ShareData1 /*implements Runnable*/{
- /* private int count = 100;//多窗口卖票
- @Override
- public void run() {
- while(true){
- count--;
- }
- }*/
- private int j = 0;
- //该线程实现的是每次加1,synchronized实现互斥
- public synchronized void increment(){
- j++;
- }
- public synchronized void decrement(){//该线程实现的是每次减1
- j--;
- }
- }
总结:
- 如果每个线程执行的代码相同可以使用同一个Runnable对象,这个Runnable对象中有那个共享的数据,例如上面的注释部分,卖票系统可以这么做。
- 如果每个线程执行的代码不同,这时候需要不同的Runnable对象,有以下两种方式来实现这些Runnable对象之间的数据共享:
方法一:将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象,每隔线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对该数据进行的各个操作的互斥和通信。如上面的方法2。
方法:将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。如上面的方法1。