1.在《Java編程思想》第4版併發一章的“21.5.3 生產者與消費者”節看到的生產者和消費者定義了兩個對象,分別在對象內部使用自身調用wait(就是synchronized(this)內部 調用了 wait() , 後面的notify再synchronized(另外一個對象 比如restaurant.chef) 調用另外一個對象的notifyAll(); 這種方法相當於是生產者和消費者都要加鎖和通知,有些繁瑣?(或者有誰覺得更好?歡迎討論) 之前面試有遇到生產者消費者的問題。 我:想到的是使用兩個同步的對象。 面試官:太複雜了,一個就可以。 我:那應該也可以,但是當時沒有具體的用語言實現,所以細節上面沒有考慮的太多。 剛上網搜索了一下,發現有使用多種實現方法來實現的(強!)應該是花了一些時間的。 Java生產者消費者的三種實現 https://www.cnblogs.com/xindoo/p/11426659.html 看他的第一種實現,使用了一個隊列。把這個隊列作爲鎖對象。於是想到能不能簡化一下,使用一個產品對象來做互斥呢? 具體實現:定義了一個String的product對象。 然後使用product做同步。初值賦值的是“”。 生產者:當product != ""時,使用product.wait等待。否則就給product賦值當前時間的字符串。然後調用product.notifyAll()通知。 消費者:當product == ""時,使用product.wait等待。否則就給product賦值"",然後調用product.notifyAll()通知。 初看起來好像是沒有問題,但是運行起來就是一直在不停的循環執行下去。 這裏犯了幾個錯誤: 1)開始的時候沒有加入通知對方的方法,生產者和消費者都只加了wait,使得兩個線程啓動之後,只執行了一個. 當時只執行了生產者的方法。消費者根本沒有執行。 2)加入product.notifyAll()的方法。但是執行還是一次。返回去對比前面文章的實現。 3)對比發現沒有在生產者和消費者的run()方法裏面加入死循環,導致執行一次就結束了。 4)加入死循環,但是會不停的執行下去,沒有按照設定的方式交替運行。 這個可能是什麼原因呢? 思考? 對了這裏synchronized的對象是String對象,被賦值不同的值的時候,會發生改變!!!從而使得同步失效!!! 於是定義了一個final的Object對象,作爲生產者和消費者的公用的一個同步對象,問題解決(記錄下來備忘)。 代碼如下: package com.study.arch.studyalgrithom.thread; public class ProducerConsumer { private final Object syncObject = new Object(); //注意這裏synchronized使用的同步對象不能是變化的,否則就鎖不住了,會出錯!! private String product = ""; //注意不能使用這個對象來做鎖,因爲這個對象在變化。但是如果使用隊列,因爲一開始就new了一個對象,所以不會變化,可以作爲同步的對象的。 class Producer implements Runnable { @Override public void run() { while (!Thread.interrupted()) { synchronized (syncObject) { while (product != "") { try { System.out.println("Producer#####product.wait()-------" + product); syncObject.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } product = System.currentTimeMillis() + "------"; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Producer#####" + product); syncObject.notifyAll(); } } } } class Consumer implements Runnable { @Override public void run() { while (!Thread.interrupted()) { synchronized (syncObject) { while (product == "") { System.out.println("Consumer#####product.wait()-------" + product); try { syncObject.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Consumer######product=" + product); product = ""; syncObject.notifyAll(); } } } } public void work() { Thread producerThread = new Thread(new Producer()); Thread consumerThread = new Thread(new Consumer()); producerThread.start(); consumerThread.start(); try { Thread.currentThread().join(); } catch (InterruptedException e) { e.printStackTrace(); } } }
生產者消費者模式的Java實現
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.