zoukankan      html  css  js  c++  java
  • 如何在两个线程间共享数据?

    如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。实现Runnable接口或callable接口,适合多个相同或不同的程序代码的线程去共享同一个资源。

    多个线程共享数据分两种情况:

    1、如果多个线程执行同一个Runnable实现类中的代码,此时共享的数据放在Runnable实现类中;

    2、如果多个线程执行不同的Runnable实现类中的代码,此时共享数据和操作共享数据的方法封装到一个对象中,在不同的Runnable实现类中调用操作共享数据的方法。

    一、 相同程序代码的多个线程共享一个资源

    如果有多个线程在同时运行同一段段代码,可以使用同一个Runnable实现类,多个线程可以共享一个实现类对象,共享数据作为这个Runnable实现类的全局变量

    卖票案例:

    public class Demo08 {
        public static void main(String[] args) {
            //创建线程任务对象
    
            Ticket ticket = new Ticket();
            //创建三个窗口对象
            Thread t1 = new Thread(ticket, "窗口1");
            Thread t2 = new Thread(ticket, "窗口2");
            Thread t3 = new Thread(ticket, "窗口3");
            //卖票
            t1.start();
            t2.start();
            t3.start();
        }
        static class Ticket implements Runnable {
            //Object lock = new Object();
            ReentrantLock lock = new ReentrantLock();
            private int ticket = 10;
            public void run() {
                String name = Thread.currentThread().getName();
                while (true) {
                    sell(name);
                    if (ticket <= 0) {
                        break;
                    }
                }
            }
            private synchronized void sell(String name) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }if (ticket > 0) {
                    System.out.println(name + "卖票:" + ticket);
                    ticket--;
                }
            }
        }
    }

    ticket就是全局变量,作为三个线程的共享数据。

    二、 不同程序代码的多个线程共享一个资源

    如果每个线程执行的代码不同,将共享数据和操作共享数据的方法封装在一个对象中,在不同的Runnable实现类调用操作共享数据的方法。

    银行转账案例:

    创建一个对象,对象中有操作共享数据的方法

    public class Bank {
    
        private volatile int count =0;//账户余额
    
        //存钱
        public  void addMoney(int money){
            count +=money;
            System.out.println(System.currentTimeMillis()+"存进:"+money);
        }
    
        //取钱
        public  void subMoney(int money){
            if(count-money < 0){
                System.out.println("余额不足");
                return;
            }
            count -=money;
            System.out.println(+System.currentTimeMillis()+"取出:"+money);
        }
    
        //查询
        public void lookMoney(){
            System.out.println("账户余额:"+count);
        }
    }

    创建两个线程,线程中分别调用共享数据所在对象中不同的方法,

    public class SyncThreadTest {
    
        public static void main(String args[]){
            final Bank bank=new Bank();
    
            Thread tadd=new Thread(new Runnable() {
    
                public void run() {
                    // TODO Auto-generated method stub
                    while(true){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        bank.addMoney(100);
                        bank.lookMoney();
                        System.out.println("
    ");
    
                    }
                }
            });
    
            Thread tsub = new Thread(new Runnable() {
    
                public void run() {
                    // TODO Auto-generated method stub
                    while(true){
                        bank.subMoney(100);
                        bank.lookMoney();
                        System.out.println("
    ");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
            tsub.start();
            tadd.start();
        }
    }

    如果一个类继承Thread,则不适合资源共享。并不是不可以实现资源共享

    生产者与消费者问题

    包子铺线程生产包子,吃货线程消费包子。当包子没有时(包子状态为false),吃货线程等待,包子铺线程生产包子(即包子状态为true),并通知吃货线程(解除吃货的等待状态),因为已经有包子了,那么包子铺线程进入等待状态。接下来,吃货线程能否进一步执行则取决于锁的获取情况。如果吃货获取到锁,那么就执行吃包子动作,包子吃完(包子状态为false),并通知包子铺线程(解除包子铺的等待状态),吃货线程进入等待。包子铺线程能否进一步执行则取决于锁的获取情况。

    包子资源类:
    吃货线程类:
    包子铺线程类:

     

    实现Runnable接口比继承Thread类所具有的优势:

    1. 适合多个相同的程序代码的线程去共享同一个资源。

    2. 可以避免java中的单继承的局限性。

    3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立

    4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。

     
  • 相关阅读:
    Objective-C基础教程读书笔记(6)
    Objective-C基础教程读书笔记(7)
    [置顶] android网络通讯之HttpClient4不指定参数名发送Post
    一些常见的正在表达式
    给EditText中的图片加监听
    HDU 4569Special equations2012长沙邀请赛E题(数学知识)
    Linux malloc大内存的方法
    优秀员工的做法-领先的专业、道路管理
    ZOJ 3324 Machine
    DateUtil
  • 原文地址:https://www.cnblogs.com/zwh0910/p/14354344.html
Copyright © 2011-2022 走看看