多个线程之间共享数据

来源:互联网 发布:马踏棋盘 栈 贪婪算法 编辑:程序博客网 时间:2024/04/30 18:59

多个线程之间共享数据,首先想到的是将共享数据设置为全局变量,并且用static修饰,但是static修饰的变量是类变量,生命周期太长了,占用内存,本文将介绍三种方法实现多个线程之间共享数据。

方法一:多个线程对共享数据的操作是相同的,那么创建
一个Runnable的子类对象,将这个对象作为参数传递给Thread的构造方法,此时因为多个线程操作的是同一个Runnable的子类对象,所以他们操作的是同一个共享数据。比如:买票系统,所以的线程的操作都是对票数减一的操作。
代码如下:

public class MutilThreadShareDate{    public static void main(String[] args) {        oneRunnable();    }    //买票系统    public static void oneRunnable(){        ShareDate1 date1 = new ShareDate1();        // 因为四个线程访问的是同一个date对象,所以数据之间可以共享        new Thread(date1).start();        new Thread(date1).start();        new Thread(date1).start();        new Thread(date1).start();    }}class ShareDate1 implements Runnable {    int j = 100;//共享变量    public synchronized void decrement() {    System.out.println(Thread.currentThread().getName() + ",做j--的操作," + j);        j--;    }    @Override    public void run() {        /*         * 怎么做到线程安全,保证,让票数大于0呢?         * 因为票数j属于共享数据,当j满足条件时进去while循环,while循环中加了锁,保证线程安全         * 当多个线程进入了while循环,在等待锁的时,别的线程对j进行了j--的操作,当j减到0时,等待的线程获得锁之后,还会继续做j--的操作,导致j为负数,所以要对j再次加一判断。         */        while (j > 0) {            synchronized (this) {                if (j > 0) {                    //让当前线程停下10ms,让出cpu的执行权,其他线程不能获得锁,但是可以运行不需要该锁的代码。10s中到了,就自动向下执行                    try {                        Thread.sleep(10);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    decrement();                }            }        }    }}

方法二:多个线程对共享数据的操作是不同的,将共享数据和操作共享数据的方法放在同一对象中,将这个对象作为参数传递给Runnable的子类,在子类中用该对象的方法对共享数据进行操作。如:生产者消费则。
代码如下:

public class MutilThreadShareDate{    public static void main(String[] args) {        twoRunnable2();    }public static void twoRunnable2(){        final ShareDate1 date1 = new ShareDate1();        new Thread(new MyRunnable1(date1)).start();        new Thread(new MyRunnable2(date1)).start();    }}//创建两个Runnable的子类对象,对象接收一个参数,对这个参数进行操作,实现数据间的共享class MyRunnable1 implements Runnable{    private ShareDate1 date1;    public MyRunnable1(ShareDate1 date1){        this.date1 = date1;    }    @Override    public void run() {        while(date1.j > 100){            date1.decrement();        }    }}//创建两个Runnable的子类对象,对象接收一个参数,对这个参数进行操作,实现数据间的共享class MyRunnable2 implements Runnable{    private ShareDate1 date1;    public MyRunnable2(ShareDate1 date1){        this.date1 = date1;    }    @Override    public void run() {        while(date1.j < 200){            date1.increment();        }    }}//共享数据所在的类class ShareDate1 implements Runnable {    int j = 100;    public synchronized void increment() {        System.out.println(Thread.currentThread().getName() + ",做j++的操作," + j);        j++;    }    public synchronized void decrement() {        System.out.println(Thread.currentThread().getName() + ",做j--的操作," + j);        j--;    }    @Override    public void run() {        /*         * 怎么做到线程安全,保证,票数大于0呢?         * 因为票数j属于共享数据,当j满足条件时进去while循环,while循环中加了锁,保证线程安全         * 当多个线程进入了while循环,在等待锁的时,别的线程对j进行了j--的操作,当j减到0时,等待的线程获得锁之后,还会继续做j--的操作,导致j为负数,所以要对j再次加一判断。         */        while (j > 0) {            synchronized (this) {                if (j > 0) {                    //让当前线程停下10ms,让出cpu的执行权,其他线程不能获得锁,但是可以运行不需要锁的代码。                    try {                        Thread.sleep(10);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    decrement();                }            }        }    }}

方法三:多个线程对共享数据的操作是不同的, 用内部类的方式去实现,创建Runnable的子类作为内部类,将共享对象作为全局变量,在Runnable的子类中对共享数据进行操作。
代码如下:

public class MutilThreadShareDate{    public static void main(String[] args) {        twoRunnable1();    }public static void twoRunnable1(){        //内部类调用外部类的对象,外部类的对象必须用final修饰,保证内部类不能修改他。        final ShareDate1 date1 = new ShareDate1();        /*         * 因为这两个线程操作的是同一个对象,所以用的是同一个j,这个j在两个线程中间是共享的。         */        new Thread(            new Runnable(){                @Override                public void run() {                    date1.increment();                }            }        ).start();        new Thread(                new Runnable(){                    @Override                    public void run() {                        date1.decrement();                    }                }            ).start();    }}//共享数据所在的类class ShareDate1 implements Runnable {    int j = 100;    public synchronized void increment() {        System.out.println(Thread.currentThread().getName() + ",做j++的操作," + j);        j++;    }    public synchronized void decrement() {        System.out.println(Thread.currentThread().getName() + ",做j--的操作," + j);        j--;    }    @Override    public void run() {        /*         * 怎么做到线程安全,保证,票数大于0呢?         * 因为票数j属于共享数据,当j满足条件时进去while循环,while循环中加了锁,保证线程安全         * 当多个线程进入了while循环,在等待锁的时,别的线程对j进行了j--的操作,当j减到0时,等待的线程获得锁之后,还会继续做j--的操作,导致j为负数,所以要对j再次加一判断。         */        while (j > 0) {            synchronized (this) {                if (j > 0) {                    //让当前线程停下10ms,让出cpu的执行权,其他线程不能获得锁,但是可以运行不需要锁的代码。                    try {                        Thread.sleep(10);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    decrement();                }            }        }    }}
0 0
原创粉丝点击