六、多线程基础-多个线程行为不一致/一致共同操作一个数据的设计方法

1、多个线程行为不一致共同操作一个数据
如果每个线程执行的代码不同,这时候需要用不同的 Runnable 对象:
有如下两种方法:
方法1)将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个 Runnable 对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。见示列1:ShareDataThreadDifferent

public class ShareDataThreadDifferent {
    public static void main(String[] args) {
        ShareData1 shareData = new ShareData1();
        for (int i = 0; i < 4; i++) {
            if (i % 2 == 0) {//%是求模运算符   /是除运算符
                new Thread(new RunnableCusToInc1(shareData), "Thread " + i)
                        .start();
            } else {
                new Thread(new RunnableCusToDec(shareData), "Thread " + i)
                        .start();
            }
        }
    }
}

/**
 * 共享数据类
 **/
class ShareData1 {
    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.out.println(Thread.currentThread().getName()
                + ": invoke dec method num =" + num);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// 封装共享数据类的Runnable类1
class RunnableCusToInc1 implements Runnable {
    // 封装共享数据
    private ShareData1 shareData;

    public RunnableCusToInc1(ShareData1 data) {
        this.shareData = data;
    }

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

// 封装共享数据类Runnable类2
class RunnableCusToDec implements Runnable {
    // 封装共享数据
    private ShareData1 shareData;

    public RunnableCusToDec(ShareData1 data) {
        this.shareData = data;
    }

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

运行结果:

Thread 0: invoke inc method num =11
Thread 0: invoke inc method num =12
Thread 3: invoke dec method num =11
Thread 2: invoke inc method num =12
Thread 1: invoke dec method num =11
Thread 1: invoke dec method num =10
Thread 2: invoke inc method num =11
Thread 2: invoke inc method num =12
Thread 2: invoke inc method num =13
Thread 2: invoke inc method num =14
Thread 3: invoke dec method num =13
Thread 0: invoke inc method num =14
Thread 3: invoke dec method num =13
Thread 3: invoke dec method num =12
Thread 3: invoke dec method num =11
Thread 1: invoke dec method num =10
Thread 1: invoke dec method num =9
Thread 1: invoke dec method num =8
Thread 0: invoke inc method num =9
Thread 0: invoke inc method num =10
View Code

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

public class ShareDataThreadDifferent2 {//外部类
    public static void main(String[] args) {
        // 公共数据
        final ShareData2 shareData = new ShareData2();//共享数据类
        for (int i = 0; i < 4; i++) {
            if (i % 2 == 0) {
                new Thread(new Runnable() {//内部类
                    public void run() {
                        for (int i = 0; i < 5; i++) {
                            shareData.inc();//对共享数据的操作
                        }
                    }
                }, "Thread " + i).start();
            } else {
                new Thread(new Runnable() {
                    public void run() {
                        for (int i = 0; i < 5; i++) {
                            shareData.dec();
                        }
                    }
                }, "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();
        }
    }

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

运行结果:

Thread 0: invoke inc method num =11
Thread 2: invoke inc method num =12
Thread 2: invoke inc method num =13
Thread 3: invoke dec method num =12
Thread 3: invoke dec method num =11
Thread 1: invoke dec method num =10
Thread 1: invoke dec method num =9
Thread 1: invoke dec method num =8
Thread 1: invoke dec method num =7
Thread 1: invoke dec method num =6
Thread 3: invoke dec method num =5
Thread 2: invoke inc method num =6
Thread 0: invoke inc method num =7
Thread 0: invoke inc method num =8
Thread 2: invoke inc method num =9
Thread 3: invoke dec method num =8
Thread 2: invoke inc method num =9
Thread 0: invoke inc method num =10
Thread 3: invoke dec method num =9
Thread 0: invoke inc method num =10
View Code

2、多个线程行为一致共同操作一个数据:
如果每个线程执行的代码相同,可以使用同一个 Runnable 对象,这个Runnable 对象中有那个共享数据, 例如:买票系统就可以这么做

public class ShareDataThreadUniformity {
    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();
        }
    }
}
View Code

运行结果:

Thread 0: invoke inc method num =11
Thread 3: invoke inc method num =12
Thread 2: invoke inc method num =13
Thread 2: invoke inc method num =14
Thread 2: invoke inc method num =15
Thread 2: invoke inc method num =16
Thread 2: invoke inc method num =17
Thread 1: invoke inc method num =18
Thread 1: invoke inc method num =19
Thread 1: invoke inc method num =20
Thread 1: invoke inc method num =21
Thread 1: invoke inc method num =22
Thread 3: invoke inc method num =23
Thread 0: invoke inc method num =24
Thread 3: invoke inc method num =25
Thread 3: invoke inc method num =26
Thread 3: invoke inc method num =27
Thread 0: invoke inc method num =28
Thread 0: invoke inc method num =29
Thread 0: invoke inc method num =30
View Code

 

posted @ 2018-09-10 20:03  爱笑的berg  阅读(1233)  评论(0编辑  收藏  举报