`
lvwenwen
  • 浏览: 955906 次
  • 性别: Icon_minigender_1
  • 来自: 魔都
社区版块
存档分类
最新评论

主线程跟子线程怎么通讯 java

阅读更多
学到多线程,编了一个简单地电脑城进出货模拟系统。
代码有点长,主要部分如下所述:
有三方:厂家,电脑城,顾客
厂家2个,一个生产主板,一个生产显卡。
顾客有2个,他们各自不断购买主板和显卡。
电脑城有一个,卖显卡和主板。
限于篇幅问题,摘录主要代码如下:
--------------------------厂家类---------------------------------------
Java代码 
public class Mainboardretailer implements Runnable// 主板厂家 
{    
       public void run() 
    { 
        while(true) 
        { 
        电脑城.stockMainboard(deliverMB("MSI"));//不断向电脑城供货 
        } 
    } 
 
    public Mainboard deliverMB(String 主板名) 
    { 
        return 主板; 
    } 
 

public class Videocardretailer implements Runnable// 显卡厂家 
{    
        public void run() 
    { 
        while(true) 
        { 
        电脑城.stockVideocard(deliverVC("ATI"));//不断向电脑城供货 
        } 
    } 
    public videocard deliverMB(String 显卡名) 
    { 
        return 显卡; 
    } 
 


-------------------------------------顾客类-------------------------------------------
Java代码 
public class customer implements Runnable 

    public void run() 
    { 
        while(true) 
        { 
            buyVC("ATI"); 
            //顾客不断购买显卡和主板 
            buyMB("MSI"); 
        } 
    } 
 


-----------------------------电脑城类-----------------------------------------
Java代码 
public class ComputerCenter  

    int MAXVCSTORE = 100;//货仓容量 
    int MAXMBSTORE = 100;//货仓容量 
    private static LinkedList<Videocard> VideocardQty = new LinkedList<Videocard>();//显卡货仓 
    private static LinkedList<Mainboard> MainboardQty = new LinkedList<Mainboard>();//主板货仓 
     
    public synchronized void stockVideocard(Videocard VCname) 
    { 
        if(VideocardQty.size() >= MAXVCSTORE) 
        { 
            System.out.println("ComputerCenter: the VC storage is MAX"); 
            try  
            { 
                wait();//---------------------当存货过多时。通知厂商等待。 
            } catch (InterruptedException e)  
            { 
                e.printStackTrace(); 
            } 
        } 
            VideocardQty.add(VCname); 
            notify();//----------------------------唤醒消费者消费 
    } 
     
    public synchronized void stockMainboard(Mainboard MBname) 
    { 
        if(MainboardQty.size() >= MAXVCSTORE) 
        { 
            System.out.println("ComputerCenter: the MB storage is MAX"); 
            try  
            { 
                wait();//----------------------当存货过多时。通知厂商等待。 
            } catch (InterruptedException e)  
            { 
                e.printStackTrace(); 
            } 
        } 
            MainboardQty.add(MBname); 
            notify();//-----------------------------唤醒消费者消费 
    } 
     
    public synchronized Videocard sellVideocard(String VCname) 
    { 
        if(VideocardQty.size() <= 0) 
        { 
            try 
            { 
                wait();//-----------------没有存货时,通知消费者等待 
            }catch(Exception e) 
            { 
                e.printStackTrace(); 
            } 
        } 
            notify();//----------------------------------唤醒厂商 
            return MyVideocard; 
    } 
     
    public synchronized Mainboard sellMainboard(String MBname) 
    { 
        if(MainboardQty.size() <= 0) 
        { 
            try 
            { 
                wait();//-----------------没有存货时,通知消费者等待 
            }catch(Exception e) 
            { 
                e.printStackTrace(); 
            } 
        } 
            notify();//----------------------------------唤醒厂商 
            return MyMainboard; 
    } 
     
    public static void main(String[] args) 
    { 
        ComputerCenter MyCC = new ComputerCenter(); 
        new customer(MyCC,"Jack").start(); 
        new customer(MyCC,"Tom").start(); 
        new Mainboardretailer(MyCC).start(); 
        new Videocardretailer(MyCC).start(); 
    } 
 




现在出现了这样的一个问题:
1.如果有两个消费者同时等待,厂家生产后唤醒其中消费者A,消费者A购买完毕后会唤醒消费者B--不合逻辑。
2.如果购买显卡地消费者A在等待,电脑城从主板厂商进货了主板以后会唤醒消费者A。同样的情况也发生在购买主板的消费者B身上。
3.如果两家厂商在等待消费者购买商品,此时消费者A购买了主板,货仓主板数量-1,然后有可能唤醒显卡厂商而没有唤醒主板厂商进行生产。
4.如果两家厂商正在等待消费者购买商品,此时显卡厂商被唤醒后,可能立刻唤醒主板厂商生产主板,令到商品数量超出仓库上限。

我想,有没有什么办法,可以指定唤醒某个线程?如果可以,那问题就容易解决了。

------------------------------------------------------------------------------------------------------------------
问题补充:
xmind 写道
主要问题是 显卡 没了,等显卡送来,主板没了等主板送来。
不能人家来买显卡的,你进来一个主板也通知人家来买。
写了个例子,你看看。
Java代码 
class ComputerCenter { 
    private static Object VIDEO = new Object(); 
    private static Object MAINB = new Object(); 
    private static Integer videoN = 10; 
    private static Integer MainbN = 10; 
 
    public void stockVd() { 
        synchronized(VIDEO) { 
            if(videoN >= 20) { 
                System.out.println("ComputerCenter: the VC storage is MAX");    
                try {VIDEO.wait();} catch (Exception e) {}    
            } 
            System.out.println("ComputerCenter: 厂商送来一块显卡。"); 
            videoN++; 
            VIDEO.notify();//----------------------------唤醒消费者消费 
        } 
    } 
 
    public void stockMd() { 
        synchronized(MAINB) { 
            if(MainbN >= 20) { 
                System.out.println("ComputerCenter: the MB storage is MAX");    
                try {MAINB.wait();} catch (Exception e) {}       
            } 
            System.out.println("ComputerCenter: 厂商送来一块主板。"); 
            MainbN++; 
            MAINB.notify();//-----------------------------唤醒消费者消费 
        } 
    } 
 
    public void sellVd(String name) {    
        synchronized(VIDEO) { 
            if(videoN <= 0) { 
                System.out.println("没有显卡了,等等,马上送来!!!!!!!!!");    
                try {VIDEO.wait();} catch (Exception e) {}     
            } 
            System.out.println(name + " : 买走一块显卡。"); 
            videoN--; 
            VIDEO.notify();//----------------------------------唤醒厂商 
        } 
    } 
     
    public void sellMd(String name)  { 
        synchronized(MAINB) { 
            if(MainbN <= 0) {   
                System.out.println("没有主板了,等等,马上送来!!!!!!!!!!");    
                try {MAINB.wait();} catch (Exception e) {}  
            } 
            System.out.println(name + " : 买走一块主板。"); 
            MainbN--; 
            MAINB.notify();//----------------------------------唤醒厂商 
        } 
    } 
 
 
    public static void main(String[] args) { 
        ComputerCenter MyCC = new ComputerCenter();    
        new customer(MyCC,"Jack").start(); 
        new customer(MyCC,"Tom").start();   
        new Md_retailer(MyCC).start(); 
        new Vd_retailer(MyCC).start(); 
    } 

 
class customer extends Thread { 
    private ComputerCenter cc; 
    private String name; 
    public customer(ComputerCenter cc,String name) { 
        this.cc = cc; 
        this.name = name; 
    } 
 
    public void run() { 
        while(true) { 
            //try {Thread.sleep(10);} catch (Exception e) {}       
            //顾客不断购买显卡和主板    
            cc.sellVd(name);    cc.sellMd(name); 
        } 
    }   

class Md_retailer extends Thread { 
    private ComputerCenter cc; 
    public Md_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockMd(); 
        } 
    }   

class Vd_retailer extends Thread { 
    private ComputerCenter cc; 
    public Vd_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockVd(); 
        } 
    }   



注释掉不同地方的 try {Thread.sleep(10);} catch (Exception e) {} 可以模拟不同的情况。



非常感谢您,我修改了一下代码,用synchronized代码块来指定唤醒地对象。但是依然有一个问题:当有2人同时在等待买显卡地时候,厂商送来一块显卡,A买完后,却会唤醒B去买。这里有逻辑错误。该怎么样改进一下呢?
其实还有有种办法解决,就是通过在wait()那里套一个while(iswaiting)来实现唤醒指定地线程。电脑城进货后,改变某个boolean值,唤醒所有线程。那些没有被改变boolean值的线程将被套在while循环里面。这样可以解决问题,但我总觉得怪怪地不自然。

------------------------------------------------------------------------------------------------------------------
问题补充:
xmind 写道
噢,对不起,我是没有考虑这个情况。
你说的那种方法应该能够实现,我等待后再判断的方法试了试,要使,你看看
Java代码 
public void sellMd(String name)  { 
        synchronized(MAINB) { 
            if(MainbN <= 0) { 
                System.out.println("没有主板了,等等,马上送来!!!!!!!!!!");    
                try {MAINB.wait();} catch (Exception e) {}  
            } 
            if(MainbN >0) { 
                System.out.println(name + " : 买走一块主板。"+MainbN); 
                MainbN--; 
            } 
            MAINB.notify();//----------------------------------唤醒厂商 
        } 
    } 


谢谢您。我觉得呢,这样子看上去是可行的,但还有一点逻辑上的错误。假如A,B都在等待买显卡,此时电脑城获得一块显卡,库存显卡数为1,通知AB其中一个。假设A买到了显卡,显卡库存变为0。此时A唤醒B。B醒来后if判断显卡数不大于0,所以并没有买走显卡,但是他却被唤醒并离开了,也就是说他这次不买显卡了(他本来是想买显卡的,只不过没货,在等待)。并且他离开时通知了电脑城再进一块显卡(如果此时达到库存上线,厂商在等待消费,那么它将被B唤醒而生产显卡,导致电脑城显卡数超出库存)。
这里是不是有点逻辑上的小漏洞呢?大家探讨探讨。

------------------------------------------------------------------------------------------------------------------
问题补充:
hareamao 写道


Java代码 
import java.util.ArrayDeque; 
 
public class StockManager { 
    private final Object producerLock = new Object(); 
    private final Object consumerLock = new Object(); 
    private final int MAX_SIZE = 10; 
 
    private final ArrayDeque<Product> queue = new ArrayDeque<Product>(); 
 
    public void stock(Product p) throws InterruptedException { 
        synchronized (producerLock) { 
            if (queue.size() >= MAX_SIZE) { 
                producerLock.wait(); 
            } 
        } 
        synchronized (queue) { 
            queue.add(p); 
        } 
        synchronized (consumerLock) { 
            consumerLock.notify(); 
        } 
    } 
 
    public synchronized Product purchase() throws InterruptedException { 
        synchronized (consumerLock) { 
            if (queue.size() <= 0) { 
                consumerLock.wait(); 
            } 
        } 
        Product product = null; 
        synchronized (queue) { 
            product = queue.remove(); 
        } 
        synchronized (producerLock) { 
            producerLock.notify(); 
        } 
        return product; 
    } 


lz基本的问题就是,厂商和客户等的不是同一把锁,所以要分别对待。然后就简单了。不过我的StockManager看着也不怎么对劲儿。


阁下的方法是,将StockManager分开实例化令厂商解锁时只解在自己队列上排队的顾客,从而避免了唤醒另外一条队的顾客。这样子也可以。thanks。
另外问一句,为什么阁下的代码中这么多final的?

采纳的答案

2010-07-26 hareamao (高级程序员)
没怎么写过多线程,拿来练练手,未必正确。

Java代码 
public class Product { 
    private String name; 
    private int serial; 
 
    public String getName() { 
        return name; 
    } 
 
    public void setName(String name) { 
        this.name = name; 
    } 
 
    public int getSerial() { 
        return serial; 
    } 
 
    public void setSerial(int serial) { 
        this.serial = serial; 
    } 


Java代码 
import java.util.ArrayDeque; 
 
public class StockManager { 
    private final Object producerLock = new Object(); 
    private final Object consumerLock = new Object(); 
    private final int MAX_SIZE = 10; 
 
    private final ArrayDeque<Product> queue = new ArrayDeque<Product>(); 
 
    public void stock(Product p) throws InterruptedException { 
        synchronized (producerLock) { 
            if (queue.size() >= MAX_SIZE) { 
                producerLock.wait(); 
            } 
        } 
        synchronized (queue) { 
            queue.add(p); 
        } 
        synchronized (consumerLock) { 
            consumerLock.notify(); 
        } 
    } 
 
    public synchronized Product purchase() throws InterruptedException { 
        synchronized (consumerLock) { 
            if (queue.size() <= 0) { 
                consumerLock.wait(); 
            } 
        } 
        Product product = null; 
        synchronized (queue) { 
            product = queue.remove(); 
        } 
        synchronized (producerLock) { 
            producerLock.notify(); 
        } 
        return product; 
    } 


Java代码 
import java.util.logging.Logger; 
 
public class Producer implements Runnable{ 
    private static final Logger log = Logger.getLogger(Producer.class.getName()); 
 
    private String productName = null; 
    private int serial = 0; 
    private StockManager stockManager; 
 
    public void setProductName(String productName) { 
        this.productName = productName; 
    } 
 
    public void setStockManager(StockManager stockManager) { 
        this.stockManager = stockManager; 
    } 
 
    public Product produce() { 
        final Product p = new Product(); 
        p.setName(productName); 
        p.setSerial(++serial); 
        return p; 
    } 
 
    @Override 
    public void run() { 
        try { 
            for( int i = 0; i < 20; i++) { 
                deliver(); 
            } 
            Thread.sleep(30 * 1000); 
            while (true) { 
                deliver(); 
            } 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    private void deliver() throws InterruptedException { 
        final long s = System.currentTimeMillis(); 
        final Product product = produce(); 
        stockManager.stock(product); 
        final long time = System.currentTimeMillis() - s; 
        if (time > 10) { 
            log.info(product.getName() + ", No. " + 
                    product.getSerial() + " took " + 
                    time + " milli seconds to finish." ); 
        } 
    } 


Java代码 
import java.util.logging.Logger; 
 
public class Consumer implements Runnable { 
    private static final Logger log = Logger.getLogger(Consumer.class.getName()); 
 
    private String name; 
    private StockManager[] stockManagers; 
 
    public void setName(String name) { 
        this.name = name; 
    } 
 
    public void setStockManagers(StockManager[] stockManagers) { 
        this.stockManagers = stockManagers; 
    } 
 
    @Override 
    public void run() { 
        for (int i = 0; i < 50; i++) { 
            final double v = Math.random() * stockManagers.length; 
            final int k = (int) Math.floor(v); 
            try { 
                final long s = System.currentTimeMillis(); 
                final Product product = stockManagers[k].purchase(); 
                final long time = System.currentTimeMillis() - s; 
                String l = ""; 
                if (time > 10) { 
                    l += "after " + time + " milli seconds of waiting, "; 
                } 
                l += (name + " bought product " + product.getName() 
                        + ", serial No. " + product.getSerial()); 
                log.info(l); 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
                break; 
            } 
 
            try { 
                Thread.sleep(100); 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
                break; 
            } 
        } 
    } 


Java代码 
public class Mall { 
    public static void main(String[] args) { 
        final StockManager mb = new StockManager(); 
        final Producer pmb = new Producer(); 
        pmb.setProductName("Motherboard"); 
        pmb.setStockManager(mb); 
 
        final StockManager vd = new StockManager(); 
        final Producer pvd = new Producer(); 
        pvd.setProductName("Video Card"); 
        pvd.setStockManager(vd); 
 
        final StockManager[] stockManagers = new StockManager[2]; 
        stockManagers[0] = mb; 
        stockManagers[1] = vd; 
 
        final Consumer c1 = new Consumer(); 
        c1.setName("C1"); 
        c1.setStockManagers(stockManagers); 
 
        final Consumer c2 = new Consumer(); 
        c2.setName("C2"); 
        c2.setStockManagers(stockManagers); 
 
        new Thread(c1).start(); 
        new Thread(c2).start(); 
 
        try { 
            Thread.sleep(2000); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
 
        new Thread(pmb).start(); 
        new Thread(pvd).start(); 
    } 



提问者对于答案的评价:
解决办法之一.
问题答案可能在这里 → 寻找更多解答

java生产者消费者经典问题
Java 关于线程同步的问题
java多线程 消费者-生产者
我有一个关于多线程编码的问题..
一段关于线程的代码 请教
其他回答

1.消费者由生产唤醒,每次唤醒队列中的一个,A买完就走,不要多管闲事
2.不同的产品在不同的队列中,不要排别人的队
3.4.同2
qinglangee (资深程序员) 2010-07-26
主要问题是 显卡 没了,等显卡送来,主板没了等主板送来。
不能人家来买显卡的,你进来一个主板也通知人家来买。
写了个例子,你看看。
Java代码 
class ComputerCenter { 
    private static Object VIDEO = new Object(); 
    private static Object MAINB = new Object(); 
    private static Integer videoN = 10; 
    private static Integer MainbN = 10; 
 
    public void stockVd() { 
        synchronized(VIDEO) { 
            if(videoN >= 20) { 
                System.out.println("ComputerCenter: the VC storage is MAX");    
                try {VIDEO.wait();} catch (Exception e) {}    
            } 
            System.out.println("ComputerCenter: 厂商送来一块显卡。"); 
            videoN++; 
            VIDEO.notify();//----------------------------唤醒消费者消费 
        } 
    } 
 
    public void stockMd() { 
        synchronized(MAINB) { 
            if(MainbN >= 20) { 
                System.out.println("ComputerCenter: the MB storage is MAX");    
                try {MAINB.wait();} catch (Exception e) {}       
            } 
            System.out.println("ComputerCenter: 厂商送来一块主板。"); 
            MainbN++; 
            MAINB.notify();//-----------------------------唤醒消费者消费 
        } 
    } 
 
    public void sellVd(String name) {    
        synchronized(VIDEO) { 
            if(videoN <= 0) { 
                System.out.println("没有显卡了,等等,马上送来!!!!!!!!!");    
                try {VIDEO.wait();} catch (Exception e) {}     
            } 
            System.out.println(name + " : 买走一块显卡。"); 
            videoN--; 
            VIDEO.notify();//----------------------------------唤醒厂商 
        } 
    } 
     
    public void sellMd(String name)  { 
        synchronized(MAINB) { 
            if(MainbN <= 0) {   
                System.out.println("没有主板了,等等,马上送来!!!!!!!!!!");    
                try {MAINB.wait();} catch (Exception e) {}  
            } 
            System.out.println(name + " : 买走一块主板。"); 
            MainbN--; 
            MAINB.notify();//----------------------------------唤醒厂商 
        } 
    } 
 
 
    public static void main(String[] args) { 
        ComputerCenter MyCC = new ComputerCenter();    
        new customer(MyCC,"Jack").start(); 
        new customer(MyCC,"Tom").start();   
        new Md_retailer(MyCC).start(); 
        new Vd_retailer(MyCC).start(); 
    } 

 
class customer extends Thread { 
    private ComputerCenter cc; 
    private String name; 
    public customer(ComputerCenter cc,String name) { 
        this.cc = cc; 
        this.name = name; 
    } 
 
    public void run() { 
        while(true) { 
            //try {Thread.sleep(10);} catch (Exception e) {}       
            //顾客不断购买显卡和主板    
            cc.sellVd(name);    cc.sellMd(name); 
        } 
    }   

class Md_retailer extends Thread { 
    private ComputerCenter cc; 
    public Md_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockMd(); 
        } 
    }   

class Vd_retailer extends Thread { 
    private ComputerCenter cc; 
    public Vd_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockVd(); 
        } 
    }   



注释掉不同地方的 try {Thread.sleep(10);} catch (Exception e) {} 可以模拟不同的情况。
xmind (中级程序员) 2010-07-26
噢,对不起,我是没有考虑这个情况。
你说的那种方法应该能够实现,我等待后再判断的方法试了试,要使,你看看
Java代码 
class ComputerCenter { 
    private static Object VIDEO = new Object(); 
    private static Object MAINB = new Object(); 
    private static Integer videoN = 10; 
    private static Integer MainbN = 10; 
 
    public void stockVd() { 
        synchronized(VIDEO) { 
            if(videoN >= 20) { 
                System.out.println("ComputerCenter: the VC storage is MAX");    
                try {VIDEO.wait();} catch (Exception e) {}    
            } 
            videoN++; 
            System.out.println("ComputerCenter: 厂商送来一块显卡。" + videoN); 
            VIDEO.notify();//----------------------------唤醒消费者消费 
        } 
    } 
 
    public void stockMd() { 
        synchronized(MAINB) { 
            if(MainbN >= 20) { 
                System.out.println("ComputerCenter: the MB storage is MAX");    
                try {MAINB.wait();} catch (Exception e) {}       
            } 
            MainbN++; 
            System.out.println("ComputerCenter: 厂商送来一块主板。"+MainbN); 
            MAINB.notify();//-----------------------------唤醒消费者消费 
        } 
    } 
 
    public void sellVd(String name) {    
        synchronized(VIDEO) { 
            if(videoN <= 0) { 
                System.out.println("没有显卡了,等等,马上送来!!!!!!!!!");    
                try {VIDEO.wait();} catch (Exception e) {}     
            } 
            if(videoN >0) { 
                System.out.println(name + " : 买走一块显卡。"+videoN); 
                videoN--; 
            } 
            VIDEO.notify();//----------------------------------唤醒厂商 
        } 
    } 
     
    public void sellMd(String name)  { 
        synchronized(MAINB) { 
            if(MainbN <= 0) { 
                System.out.println("没有主板了,等等,马上送来!!!!!!!!!!");    
                try {MAINB.wait();} catch (Exception e) {}  
            } 
            if(MainbN >0) { 
                System.out.println(name + " : 买走一块主板。"+MainbN); 
                MainbN--; 
            } 
            MAINB.notify();//----------------------------------唤醒厂商 
        } 
    } 
 
    public static void main(String[] args) { 
        ComputerCenter MyCC = new ComputerCenter();    
        new customer(MyCC,"Jack").start(); 
        new customer(MyCC,"Tom").start();   
        new Md_retailer(MyCC).start(); 
        new Vd_retailer(MyCC).start(); 
    } 

 
class customer extends Thread { 
    private ComputerCenter cc; 
    private String name; 
    public customer(ComputerCenter cc,String name) { 
        this.cc = cc; 
        this.name = name; 
    } 
 
    public void run() { 
        while(true) { 
            //try {Thread.sleep(10);} catch (Exception e) {}       
            //顾客不断购买显卡和主板    
            cc.sellVd(name);    cc.sellMd(name); 
        } 
    }   

class Md_retailer extends Thread { 
    private ComputerCenter cc; 
    public Md_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockMd(); 
        } 
    }   

class Vd_retailer extends Thread { 
    private ComputerCenter cc; 
    public Vd_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockVd(); 
        } 
    }   

xmind (中级程序员) 2010-07-26
恩,是有点儿,这样你看行不行,也就是顾客在买的时候,如果没有等待,买完后也不通知。电脑城在进货满之后不等待(或者sleep也行,让出cpu,现实中像是卖一段时间在进货),没进一个货就通知一声,只通知一个顾客。
Java代码 
class ComputerCenter { 
    private static Object VIDEO = new Object(); 
    private static Object MAINB = new Object(); 
    private static Integer videoN = 10; 
    private static Integer MainbN = 10; 
 
    public void stockVd() { 
        synchronized(VIDEO) { 
            if(videoN >= 20) { 
                System.out.println("ComputerCenter: the VC storage is MAX");    
            } else { 
                videoN++; 
                System.out.println("ComputerCenter: 厂商送来一块显卡。" + videoN); 
                VIDEO.notify();//----------------------------唤醒消费者消费 
            } 
        } 
    } 
 
    public void stockMd() { 
        synchronized(MAINB) { 
            if(MainbN >= 20) { 
                System.out.println("ComputerCenter: the MB storage is MAX");    
            } else { 
                MainbN++; 
                System.out.println("ComputerCenter: 厂商送来一块主板。"+MainbN); 
                MAINB.notify();//-----------------------------唤醒消费者消费 
            } 
        } 
    } 
 
    public void sellVd(String name) {    
        synchronized(VIDEO) { 
            if(videoN <= 0) { 
                System.out.println("没有显卡了,等等,马上送来!!!!!!!!!");    
                try {VIDEO.wait();} catch (Exception e) {}     
            } 
            System.out.println(name + " : 买走一块显卡。"+videoN); 
            videoN--; 
        } 
    } 
     
    public void sellMd(String name)  { 
        synchronized(MAINB) { 
            if(MainbN <= 0) { 
                System.out.println("没有主板了,等等,马上送来!!!!!!!!!!");    
                try {MAINB.wait();} catch (Exception e) {}  
            } 
                System.out.println(name + " : 买走一块主板。"+MainbN); 
                MainbN--; 
        } 
    } 
 
    public static void main(String[] args) { 
        ComputerCenter MyCC = new ComputerCenter();    
        new customer(MyCC,"Jack").start(); 
        new customer(MyCC,"Tom").start();   
        new Md_retailer(MyCC).start(); 
        new Vd_retailer(MyCC).start(); 
    } 

 
class customer extends Thread { 
    private ComputerCenter cc; 
    private String name; 
    public customer(ComputerCenter cc,String name) { 
        this.cc = cc; 
        this.name = name; 
    } 
 
    public void run() { 
        while(true) { 
            //try {Thread.sleep(10);} catch (Exception e) {}       
            //顾客不断购买显卡和主板    
            cc.sellVd(name);    cc.sellMd(name); 
        } 
    }   

class Md_retailer extends Thread { 
    private ComputerCenter cc; 
    public Md_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockMd(); 
        } 
    }   

class Vd_retailer extends Thread { 
    private ComputerCenter cc; 
    public Vd_retailer(ComputerCenter cc) { 
        this.cc = cc; 
    } 
 
    public void run() { 
        while(true) { 
            try {Thread.sleep(10);} catch (Exception e) {}       
            cc.stockVd(); 
        } 
    }   

xmind (中级程序员) 2010-07-26
lz基本的问题就是,厂商和客户等的不是同一把锁,所以要分别对待。然后就简单了。不过我的StockManager看着也不怎么对劲儿。
分享到:
评论

相关推荐

    Java简单实现“主线程等待所有子线程完成再继续”

    总的来说,Java提供了丰富的多线程同步机制,可以根据实际需求选择合适的方法来实现“主线程等待所有子线程完成再继续”的功能。在并发编程中,理解并灵活运用这些工具对于提高程序效率和避免死锁等问题至关重要。

    JAVA主线程等待子线程执行完毕再执行[参照].pdf

    JAVA 主线程等待子线程执行完毕再执行 JAVA 中的线程控制是非常重要的一部分,而在实际开发中,我们经常会遇到需要主线程等待子线程执行完毕再执行的情况。这种情况下,我们可以使用两种方式来实现:主动式和被动式...

    Java主线程等待子线程执行完毕

    Java 主线程等待子线程执行完毕 Java 中的多线程编程是非常重要的一部分,特别是在需要并发执行多个任务的情况下。然而,在某些情况下,我们需要等待所有子线程执行完毕后再继续执行主线程的剩余动作。这时,我们...

    子线程任务发生异常,主线程事务如何回滚

    在 Java 中,存在两种线程模型:主线程和子线程。主线程是程序的入口点,而子线程是由主线程创建的辅助线程。子线程的运行结果可以通过阻塞的方式来获取。在 Java 中,我们可以使用 Callable 或 Runnable 接口来实现...

    子线程更新主线程数据

    然而,由于线程之间的数据同步问题,直接在子线程修改主线程的数据可能会导致数据不一致或程序崩溃。本文将深入探讨如何安全、有效地在子线程中更新主线程的数据。 首先,理解线程安全。线程安全是指当多个线程访问...

    android 主线程给子线程发送消息

    在Android应用开发中,主线程(也称为UI线程)主要负责处理用户界面的更新和交互,而子线程则通常用于执行耗时的操作,如网络请求、数据库操作等,以避免阻塞主线程,保证用户界面的流畅性。本示例"android 主线程给...

    java 子线程通过观察者模式通知主线程

    主线程作为观察者,注册到这个`Observable`对象上,当子线程发出通知时,主线程的`update()`方法会被调用,从而实现通信。 4. **示例代码**:以下是一个简单的例子,演示了如何使用观察者模式来实现子线程通知主线...

    主线程如何捕获子线程的异常---马克-to-win java视频

    主线程如何捕获子线程的异常---马克-to-win java视频的介绍

    java多线程编程 在主线程main中创建两个子线程

    自己学着编写的一个JAVA多线程程序,该程序实现的功能是:在主线程main中创建两个子线程,A和B,线程A先运行,再运行B线程,当两个子线程都运行完毕后,才运行主线程,并最终结束整个程序的运行。 希望该程序对初学...

    主线程等待子多线程(无结果返回)执行完成再继续执行

    "主线程等待子多线程(无结果返回)执行完成再继续执行"这个主题就涉及到如何在Java、C#、Python等编程语言中实现这种同步机制。下面将详细讨论这个知识点。 **1. Java中的`Thread.join()`方法** 在Java中,主线程...

    主线程去控制子线程wait与notify

    总的来说,主线程控制子线程的`wait()`和`notify()`操作是Java并发编程中的高级技巧,它允许我们构建更复杂、更高效的应用程序,通过线程间的协作来解决问题。理解和掌握这些概念对于编写高并发、高性能的Java应用...

    Java多线程--让主线程等待所有子线程执行完毕

    ### Java多线程--让主线程等待所有子线程执行完毕 #### 核心知识点解析 在Java多线程环境中,让主线程等待所有子线程执行完毕是一个常见的需求,尤其是在处理大量数据或进行高性能计算时。这不仅有助于正确测量...

    java多线程代码案例(创建线程,主线程,线程优先级,线程组,线程同步,线程间的通信)

    本文将深入探讨Java多线程中的关键知识点,包括创建线程、主线程、线程优先级、线程组、线程同步以及线程间的通信。 1. **创建线程** 在Java中,可以通过两种方式创建线程:继承`Thread`类或实现`Runnable`接口。...

    多线程执行完后主程序再执行(包括需要子线程返回结果)

    为解决这个问题,我们需要使用同步机制,如Java中的`join()`方法或C#的`Thread.Join()`,让主线程等待所有子线程完成后再继续执行。当调用`join()`方法时,主线程会被阻塞,直到被调用的线程执行完毕。 例如,在...

    android demo,实现主线程handle,工作子线程threadHandle的处理

    本示例“android demo,实现主线程handle,工作子线程threadHandle的处理”专注于如何在主线程和子线程之间有效地进行通信。下面将详细讲解这个知识点。 1. 主线程(UI线程): 在Android中,主线程负责处理用户...

    子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。

    标题中的内容涉及到多线程编程,具体是一种交替执行的任务模式,即子线程循环10次,然后主线程循环100次,这样的交替过程重复50次。这是一个典型的线程交互场景,常用于实现并发任务,比如在GUI应用中更新界面或者在...

    Python多线程:主线程等待所有子线程结束代码

    4. 对每个线程调用`join()`方法,使主线程等待子线程完成。 通过这种方式,你可以确保所有子任务在主线程结束前得以完成,这对于同步和资源清理等场景非常有用。同时,理解守护线程的概念和行为对于编写健壮的多...

    子线程操作主线程的示例

    本示例将深入探讨如何在Java或C#等支持多线程的编程语言中,安全地从子线程操作主线程。 首先,我们需要理解线程同步的概念。在多线程环境中,为了防止数据竞争和确保线程安全,我们需要使用同步机制,如锁、信号量...

    Java多线程--等待所有子线程执行完的五种方法.docx

    尽管不推荐,但可以通过`Thread.sleep()`方法让主线程休眠一段时间来等待子线程。这种方法的问题在于,睡眠时间必须预估,且不准确,可能导致主线程提前唤醒或过度等待。 ### 方法二:`Thread.join()`方法 `Thread....

    子线程和主线程通过handler 双向通信

    在Android开发中,多线程通信是一个至关重要的概念,尤其是主线程(UI线程)与子线程之间的交互。本文将深入探讨如何使用Handler机制实现主线程与子线程,以及HandlerThread之间的双向通信。 首先,理解Android的...

Global site tag (gtag.js) - Google Analytics