W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
[TOC]
什么是JAVA設(shè)計(jì)模式以及作用?
設(shè)計(jì)模式是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類(lèi)編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)
使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性,本篇將介紹10種JAVA常用設(shè)計(jì)模式
## 1.JAVA 設(shè)計(jì)模式 - 單例設(shè)計(jì)模式
單例模式是一種創(chuàng)建模式,這種模式只涉及一個(gè)單獨(dú)的類(lèi),它負(fù)責(zé)創(chuàng)建自己的對(duì)象
該類(lèi)確保只創(chuàng)建單個(gè)對(duì)象,這個(gè)類(lèi)提供了一種訪問(wèn)其唯一對(duì)象的方法
單例模式目的是為了整個(gè)應(yīng)用中有且只有一個(gè)實(shí)例,所有指向該類(lèi)型實(shí)例的引用都指向這個(gè)實(shí)例
保證對(duì)象不能再類(lèi)的外部被隨意實(shí)例化,解決方法:將構(gòu)造器進(jìn)行私有化處理
保證類(lèi)創(chuàng)建的過(guò)程發(fā)生在類(lèi)的內(nèi)部,還有保證在類(lèi)的外部能拿到在類(lèi)的內(nèi)部初始化的對(duì)象
單例模式類(lèi)型:餓漢式單例,懶漢式單例
Singleton(餓漢模式)
餓漢模式,特點(diǎn)是程序加載類(lèi)的時(shí)候比較慢,但運(yùn)行時(shí)獲得對(duì)象的速度比較快,它從加載到應(yīng)用結(jié)束會(huì)一直占用資源
餓漢模式代碼:
class Singleton {
public class SingletonDemo {
public static void main(String[] args) {
Singleton1 s1 = Singleton1.getInstance();
Singleton1 s2 = Singleton1.getInstance();
System.out.println(s1==s2); //true
Singleton2 s3 = Singleton2.getInstance();
Singleton2 s4 = Singleton2.getInstance();
System.out.println(s3==s4); //true
}
}
class Singleton1{
private static final Singleton1 instance = new Singleton1(); //在內(nèi)部準(zhǔn)備好一個(gè)對(duì)象
public static Singleton1 getInstance(){
return instance;
}
private Singleton1(){}
public void show(){
System.out.println("Singleton1");
}
}
class Singleton2 {
private static Singleton2 instance;
//將instance傳遞到外部去
public static Singleton2 getInstance(){
if(instance == null){
instance = new Singleton2();
}
return instance;
}
private Singleton2(){}
}
Singleton(懶漢模式)
懶漢模式特點(diǎn),程序是運(yùn)行時(shí)獲得對(duì)象的速度比較慢,但加載類(lèi)的時(shí)候比較快
它在整個(gè)應(yīng)用的生命周期只有一部分時(shí)間在占用資源
懶漢模式代碼:
class Singleton{
private static Singleton instance = null;
public static Singleton getInstance(){// 將instance傳遞到外部去
if(instance == null){
instance = new Singleton();
}
return instance;
}
private Singleton(){}
}
public static Singleton2 getInstance(){
if(instance == null){
synchronized(Singleton2.class){
if(instance == null){
instance = new Singleton2();
}
}
}
return instance;
}
Singleton(餓漢模式) & Singleton(懶漢模式) 區(qū)別
(1)這兩種模式對(duì)于初始化較快,占用資源少的輕量級(jí)對(duì)象來(lái)說(shuō),沒(méi)有多大的性能差異,選擇懶漢式或餓漢式都沒(méi)有問(wèn)題
但是對(duì)于初始化慢,占用資源多的重 量級(jí)對(duì)象來(lái)說(shuō),就會(huì)有比較明顯的差別了
所以,對(duì)重量級(jí)對(duì)象應(yīng)用餓漢模式,類(lèi)加載時(shí)速度慢,但運(yùn)行時(shí)速度快;懶漢模式則與之相反,類(lèi)加載時(shí)速度快,但運(yùn)行時(shí)第一次獲得對(duì)象的速度慢
(2)從用戶體驗(yàn)的角度來(lái)說(shuō),我們應(yīng)該首選餓漢模式。我們?cè)敢獾却硞€(gè)程序花較長(zhǎng)的時(shí)間初始化,卻不喜歡在程序運(yùn)行時(shí)等待太久,給人一種反應(yīng)遲鈍的感覺(jué),所以對(duì)于有重量級(jí)對(duì)象參與的單例模式,筆者推薦使用餓漢模式
在JAVA語(yǔ)言中,String類(lèi)型就是使用了享元模式。String對(duì)象是final類(lèi)型,對(duì)象一旦創(chuàng)建就不可改變
在JAVA中字符串常量都是存在常量池中的,JAVA會(huì)確保一個(gè)字符串常量在常量池中只有一個(gè)拷貝
String a="abc",其中"abc"就是一個(gè)字符串常量
享元模式代碼:
public class Test {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
System.out.println(a == b);
}
}
上面的例子中結(jié)果為:true ,這就說(shuō)明a和b兩個(gè)引用都指向了常量池中的同一個(gè)字符串常量"abc"
這樣的設(shè)計(jì)避免了在創(chuàng)建N多相同對(duì)象時(shí)所產(chǎn)生的不必要的大量的資源消耗
簡(jiǎn)單工廠模式是由一個(gè)工廠對(duì)象決定創(chuàng)建出哪一種產(chǎn)品類(lèi)的實(shí)例
簡(jiǎn)單工廠模式是工廠模式家族中最簡(jiǎn)單實(shí)用的模式,工廠模式就是用來(lái)生成對(duì)象的
簡(jiǎn)單工廠設(shè)計(jì)模式作用:降低耦合
簡(jiǎn)單工廠模式代碼:
//手機(jī)標(biāo)準(zhǔn)
interface ICellPhone {
void sendMsg();
}
/* 小米手機(jī) */
class Millet implements ICellPhone {
public void sendMsg() {
}
}
/* 華為手機(jī) */
class Huawei implements ICellPhone {
public void sendMsg() {
}
}
/* 手機(jī)工廠 */
class Factory {
public static ICellPhone getInstance(String type){
ICellPhone phone = null;
if("millet".equalsIgnoreCase(type)){
phone = new Millet();
}else if("huawei".equalsIgnoreCase(type)){
phone = new Huawei();
}
return phone;
}
}
public class FactoryDemo {
public static void main(String[] args) {
ICellPhone p = Factory.getInstance("millet");
}
}
如果直接使用了被調(diào)用者對(duì)象,而且又有可能會(huì)變化,那這個(gè)代碼的可擴(kuò)展性和柔韌性就不是很強(qiáng)基于這樣的問(wèn)題,所有我們就提出把客戶端(調(diào)用者)不直接跟要調(diào)用的對(duì)象產(chǎn)生依賴關(guān)系,這樣在擴(kuò)展性和柔韌性會(huì)好一些,加入中間人,來(lái)引入工廠模式調(diào)控,單獨(dú)聲明一個(gè)工廠類(lèi),屬于被調(diào)用者這一邊,簡(jiǎn)單工廠類(lèi)只負(fù)責(zé)產(chǎn)生對(duì)象
抽象工廠模式與簡(jiǎn)單工廠模式的區(qū)別:
(1)抽象工廠模式是簡(jiǎn)單工廠方法模式的升級(jí)版本,它用來(lái)創(chuàng)建一組相關(guān)或者相互依賴的對(duì)象。它與簡(jiǎn)單工廠方法模式的區(qū)別就在于,簡(jiǎn)單工廠方法模式針對(duì)的是一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu);而抽象工廠模式則是針對(duì)的多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)
(2)在編程中,通常一個(gè)產(chǎn)品結(jié)構(gòu),表現(xiàn)為一個(gè)接口或者抽象類(lèi),也就是說(shuō),簡(jiǎn)單工廠方法模式提供的所有產(chǎn)品都是衍生自同一個(gè)2接口或抽象類(lèi),而抽象工廠模式所提供的產(chǎn)品則是衍生自不同的接口或抽象類(lèi)
(3)在抽象工廠模式中,有一個(gè)產(chǎn)品族的概念:所謂的產(chǎn)品族,是指位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中功能相關(guān)聯(lián)的產(chǎn)品組成的家族。抽象工廠模式所提供的一系列產(chǎn)品就組成一個(gè)產(chǎn)品族;而工廠方法提供的一系列產(chǎn)品稱為一個(gè)等級(jí)結(jié)構(gòu)
抽象工廠模式代碼:
interface IProduct1 {
public void show();
}
interface IProduct2 {
public void show();
}
class Product1 implements IProduct1 {
public void show() {
System.out.println("這是1型產(chǎn)品");
}
}
class Product2 implements IProduct2 {
public void show() {
System.out.println("這是2型產(chǎn)品");
}
}
interface IFactory {
public IProduct1 createProduct1();
public IProduct2 createProduct2();
}
class Factory implements IFactory{
public IProduct1 createProduct1() {
return new Product1();
}
public IProduct2 createProduct2() {
return new Product2();
}
}
public class Client {
public static void main(String[] args){
IFactory factory = new Factory();
factory.createProduct1().show();
factory.createProduct2().show();
}
}
抽象工廠模式的優(yōu)點(diǎn):
抽象工廠模式除了具有簡(jiǎn)單工廠方法模式的優(yōu)點(diǎn)外,最主要的優(yōu)點(diǎn)就是可以在類(lèi)的內(nèi)部對(duì)產(chǎn)品族進(jìn)行約束,所謂的產(chǎn)品族,一般或多或少的都存在一定的關(guān)聯(lián),抽象工廠模式就可以在類(lèi)內(nèi)部對(duì)產(chǎn)品族的關(guān)聯(lián)關(guān)系進(jìn)行定義和描述,而不必專(zhuān)門(mén)引入一個(gè)新的類(lèi)來(lái)進(jìn)行管理
抽象工廠模式的缺點(diǎn):
產(chǎn)品族的擴(kuò)展將是一件十分費(fèi)力的事情,假如產(chǎn)品族中需要增加一個(gè)新的產(chǎn)品,則幾乎所有的工廠類(lèi)都需要進(jìn)行修改,所以使用抽象工廠模式時(shí),對(duì)產(chǎn)品等級(jí)結(jié)構(gòu)的劃分是非常重要的
適用場(chǎng)景
當(dāng)需要?jiǎng)?chuàng)建的對(duì)象是一系列相互關(guān)聯(lián)或相互依賴的產(chǎn)品族時(shí),便可以使用抽象工廠模式,說(shuō)的更明白一點(diǎn),就是一個(gè)繼承體系中,如果存在著多個(gè)等級(jí)結(jié)構(gòu)(即存在著多個(gè)抽象類(lèi)),并且分屬各個(gè)等級(jí)結(jié)構(gòu)中的實(shí)現(xiàn)類(lèi)之間存在著一定的關(guān)聯(lián)或者約束,就可以使用抽象工廠模式,假如各個(gè)等級(jí)結(jié)構(gòu)中的實(shí)現(xiàn)類(lèi)之間不存在關(guān)聯(lián)或約束,則使用多個(gè)獨(dú)立的工廠來(lái)對(duì)產(chǎn)品進(jìn)行創(chuàng)建,則更合適一點(diǎn)
裝飾模式在不鏈接其結(jié)構(gòu)的情況下向現(xiàn)有對(duì)象添加新功能,它是一種結(jié)構(gòu)型模式,因?yàn)樗洚?dāng)現(xiàn)有類(lèi)的包裝器
裝飾模式創(chuàng)建一個(gè)裝飾器類(lèi)來(lái)包裝原始類(lèi)并提供其他功能
裝飾模式代碼:
interface Printer {
void print();
}
class PaperPrinter implements Printer {
@Override
public void print() {
System.out.println("Paper Printer");
}
}
class PlasticPrinter implements Printer {
@Override
public void print() {
System.out.println("Plastic Printer");
}
}
abstract class PrinterDecorator implements Printer {
protected Printer decoratedPrinter;
public PrinterDecorator(Printer d){
this.decoratedPrinter = d;
}
public void print(){
decoratedPrinter.print();
}
}
class Printer3D extends PrinterDecorator {
public Printer3D(Printer decoratedShape) {
super(decoratedShape);
}
@Override
public void print() {
System.out.println("3D.");
decoratedPrinter.print();
}
}
public class Main {
public static void main(String[] args) {
Printer plasticPrinter = new PlasticPrinter();
Printer plastic3DPrinter = new Printer3D(new PlasticPrinter());
Printer paper3DPrinter = new Printer3D(new PaperPrinter());
plasticPrinter.print();
plastic3DPrinter.print();
paper3DPrinter.print();
}
}
## 6.JAVA設(shè)計(jì)模式 - 觀察者設(shè)計(jì)模式
定義對(duì)象間一種一對(duì)多的依賴關(guān)系,使得當(dāng)每一個(gè)對(duì)象改變狀態(tài),則所有依賴于它的對(duì)象都會(huì)得到通知并自動(dòng)更新
觀察者模式中,包括以下四個(gè)角色:
(1)被觀察者:類(lèi)中有一個(gè)用來(lái)存放觀察者對(duì)象的Vector容器(之所以使用Vector而不使用List,是因?yàn)槎嗑€程操作時(shí),Vector在是安全的,而List則是不安全的),這個(gè)Vector容器是被觀察者類(lèi)的核心,另外還有三個(gè)方法:attach方法是向這個(gè)容器中添加觀察者對(duì)象;detach方法是從容器中移除觀察者對(duì)象;notify方法是依次調(diào)用觀察者對(duì)象的對(duì)應(yīng)方法。這個(gè)角色可以是接口,也可以是抽象類(lèi)或者具體的類(lèi),因?yàn)楹芏嗲闆r下會(huì)與其他的模式混用,所以使用抽象類(lèi)的情況比較多
(2)觀察者:觀察者角色一般是一個(gè)接口,它只有一個(gè)update方法,在被觀察者狀態(tài)發(fā)生變化時(shí),這個(gè)方法就會(huì)被觸發(fā)調(diào)用
(3)具體的被觀察者:使用這個(gè)角色是為了便于擴(kuò)展,可以在此角色中定義具體的業(yè)務(wù)邏輯
(4)具體的觀察者:觀察者接口的具體實(shí)現(xiàn),在這個(gè)角色中,將定義被觀察者對(duì)象狀態(tài)發(fā)生變化時(shí)所要處理的邏輯
觀察者模式代碼實(shí)現(xiàn):
abstract class Subject {
private Vector obs = new Vector();
public void addObserver(Observer obs){
this.obs.add(obs);
}
public void delObserver(Observer obs){
this.obs.remove(obs);
}
protected void notifyObserver(){
for(Observer o: obs){
o.update();
}
}
public abstract void doSomething();
}
class ConcreteSubject extends Subject {
public void doSomething(){
System.out.println("被觀察者事件");
this.notifyObserver();
}
}
interface Observer {
public void update();
}
class ConcreteObserver1 implements Observer {
public void update() {
System.out.println("觀察者1收到信息進(jìn)行處理");
}
}
class ConcreteObserver2 implements Observer {
public void update() {
System.out.println("觀察者2收到信息進(jìn)行處理");
}
}
public class Client {
public static void main(String[] args){
Subject sub = new ConcreteSubject();
sub.addObserver(new ConcreteObserver1()); //添加觀察者1
sub.addObserver(new ConcreteObserver2()); //添加觀察者2
sub.doSomething();
}
}
觀察者模式的優(yōu)點(diǎn):觀察者與被觀察者之間是屬于輕度的關(guān)聯(lián)關(guān)系,并且是抽象耦合的,這樣對(duì)于兩者來(lái)說(shuō)都比較容易進(jìn)行擴(kuò)展,觀察者模式是一種常用的觸發(fā)機(jī)制,它形成一條觸發(fā)鏈,依次對(duì)各個(gè)觀察者的方法進(jìn)行處理,但同時(shí),這也算是觀察者模式一個(gè)缺點(diǎn),由于是鏈?zhǔn)接|發(fā),當(dāng)觀察者比較多的時(shí)候,性能問(wèn)題是比較令人擔(dān)憂的。并且,在鏈?zhǔn)浇Y(jié)構(gòu)中,比較容易出現(xiàn)循環(huán)引用的錯(cuò)誤,造成系統(tǒng)假死
在JAVA設(shè)計(jì)模式中,適配器模式作為兩個(gè)不兼容接口之間的橋梁
通過(guò)使用適配器模式,可以統(tǒng)一兩個(gè)不兼容的接口
適配器設(shè)計(jì)模式代碼:
//適配器模式
public class Shipeiqi{
public static void main(String [] args){
ModificationWindow i = new ModificationWindow();
i.close();
}
}
//定義一個(gè)接口
interface IWindow{
void man();//只聲明方法,
void min();//只聲明方法
void close();//只聲明方法,
}
//定義一個(gè)抽象實(shí)現(xiàn)
abstract class MyWindow implements IWindow{
public void man(){};
public void min(){};
public void close(){};
}
//定義一個(gè)類(lèi)繼承接口
class ModificationWindow extends MyWindow{
public void close(){
System.out.println("我將實(shí)現(xiàn)關(guān)閉功能");
}
}
靜態(tài)代理設(shè)計(jì)模式:如生活當(dāng)中的代理,代駕,代購(gòu),待產(chǎn)...
代理模式(Proxy):為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)
代理模式,白了就是“真實(shí)對(duì)象”的代表,在訪問(wèn)對(duì)象時(shí)引入一定程度的間接性,因?yàn)檫@種間接性可能附和多種用途(權(quán)限的控制、對(duì)象的訪問(wèn)、遠(yuǎn)程的代理)
代理類(lèi)第一先要實(shí)現(xiàn)接口,第二要維護(hù)一個(gè)代理的對(duì)象,代理對(duì)象也是通過(guò)主題接口聲明的,再通過(guò)構(gòu)造方法或者get,set傳值,這就是靜態(tài)代理
靜態(tài)代理模式代碼:
//靜態(tài)代理設(shè)計(jì)模式
//聲明一個(gè)類(lèi)
public class Jingtai{
//主方法
public static void main(String [] args){
Person p = new Person("老王 ");//實(shí)例化Person對(duì)象
//創(chuàng)建代理對(duì)象,并把被代理對(duì)象傳進(jìn)來(lái),p傳給了Matchmaker類(lèi)中的target
Matchmaker m = new Matchmaker(p); //需要一個(gè)代理對(duì)象,把被代理對(duì)象傳過(guò)來(lái)
m.miai();//真正執(zhí)行調(diào)用的是
}
}
//定義一個(gè)接口 主題接口
interface Subject{
public void miai();//抽象方法
}
//代理相當(dāng)于代理接口的方法
//定義實(shí)現(xiàn)一個(gè)接口,相當(dāng)于被代理類(lèi)
class Person implements Subject{
private String name;//定義私有的屬性
//一參構(gòu)造方法
public Person(String name){
this.name = name;
}
//定義實(shí)現(xiàn)方法
public void miai(){
System.out.println(name+"正在相親中...");//輸出
}
}
//定義一個(gè)代理類(lèi),代理的是過(guò)程,實(shí)現(xiàn)以后,是為了實(shí)現(xiàn)方法,需要重寫(xiě)方法
class Matchmaker implements Subject{
private Subject target;//要代理的目標(biāo)對(duì)象,通過(guò)定義一個(gè)代理的對(duì)象實(shí)現(xiàn)的接口,代理一個(gè)對(duì)象或者說(shuō)一個(gè)屬性,
//可以用構(gòu)造方法傳值,也可以用get,set方法傳值
//構(gòu)造方法傳值
public Matchmaker(Subject target){
this.target = target;
}
//相親之前要做的事情,封裝起來(lái)
private void before(){
System.out.println("為代理人,匹配如意郎君");
}
//相親之后要做的事情
private void after(){
System.out.println("本次相親結(jié)束.");
}
//需要重寫(xiě)方法,相親的方法
public void miai(){
before();//調(diào)用相親之前要做的事情
target.miai();//真正執(zhí)行相親的方法,調(diào)用需要目標(biāo)對(duì)象
after();//相親之后要做的事情
}
}
迭代器模式以順序方式訪問(wèn)集合對(duì)象的元素
迭代器模式代碼:
interface Iterator {
public boolean hasNext();
public Object next();
}
class LetterBag {
public String names[] = {"R" , "J" ,"A" , "L"};
public Iterator getIterator() {
return new NameIterator();
}
class NameIterator implements Iterator {
int index;
@Override
public boolean hasNext() {
if(index < names.length){
return true;
}
return false;
}
@Override
public Object next() {
if(this.hasNext()){
return names[index++];
}
return null;
}
}
}
public class Main {
public static void main(String[] args) {
LetterBag bag = new LetterBag();
for(Iterator iter = bag.getIterator(); iter.hasNext();){
String name = (String)iter.next();
System.out.println("Name : " + name);
}
}
}
迭代器模式的優(yōu)點(diǎn):
簡(jiǎn)化了遍歷方式,對(duì)于對(duì)象集合的遍歷,還是比較麻煩的,對(duì)于數(shù)組或者有序列表,可以通過(guò)下坐標(biāo)來(lái)取得,但用戶需要在對(duì)集合了解很清楚的前提下,自行遍歷對(duì)象,但是對(duì)于hash表來(lái)說(shuō),用戶遍歷起來(lái)就比較麻煩了,而引入了迭代器方法后,用戶用起來(lái)就簡(jiǎn)單的多了,可以提供多種遍歷方式,比如說(shuō)對(duì)有序列表,我們可以根據(jù)需要提供正序遍歷,倒序遍歷兩種迭代器,用戶用起來(lái)只需要得到我們實(shí)現(xiàn)好的迭代器,就可以方便的對(duì)集合進(jìn)行遍歷了,封裝性良好,用戶只需要得到迭代器就可以遍歷,而對(duì)于遍歷算法則不用去關(guān)心
迭代器模式的缺點(diǎn):
對(duì)于比較簡(jiǎn)單的遍歷(像數(shù)組或者有序列表),使用迭代器方式遍歷較為繁瑣,像ArrayList,寧可愿意使用for循環(huán)和get方法來(lái)遍歷集合
生產(chǎn)者與消費(fèi)者模式代碼:
package cn.sc;
/**
*生產(chǎn)者與消費(fèi)者應(yīng)用案例
*sleep與wait區(qū)別
*sleep讓當(dāng)前的線程進(jìn)入休眠狀態(tài),讓出cpu,讓其他線程執(zhí)行
*如果用同步的話,有對(duì)象鎖的時(shí)候,是不會(huì)釋放的,只能等待此線程使用完,才可以使用
*wait會(huì)釋放對(duì)象鎖,必須等待其他線程喚醒
*@author JEEP-711
*
*/
public class ScXf {
public static void main(String[] args) {
Phones p = new Phones(null, null);//創(chuàng)建Phones對(duì)象
PhoneSc s = new PhoneSc(p);//創(chuàng)建PhoneSc對(duì)象
PhoneXf x = new PhoneXf(p);//創(chuàng)建PhoneXf對(duì)象
new Thread(s).start();//啟動(dòng)生產(chǎn)者線程
new Thread(x).start();//啟動(dòng)消費(fèi)者線程
}
}
/**
* 手機(jī)生產(chǎn)者,單獨(dú)的生產(chǎn)者,實(shí)現(xiàn)Runnable接口
* @author JEEP-711
*
*/
class PhoneSc implements Runnable{
private Phones phones;
public PhoneSc(Phones phones){
this.phones = phones;
}
@Override
public void run() {
//不斷地生產(chǎn)20份,生產(chǎn)的過(guò)程
for (int i = 0; i < 50; i++) {
if(i%2==0){
phones.set("金立手機(jī)", "金立手機(jī),中國(guó)造!");
}else{
phones.set("小米手機(jī)", "小米手機(jī),為發(fā)燒而生!");
}
}
}
}
/**
*手機(jī)消費(fèi)者,顧客
*@author JEEP-711
*
*/
class PhoneXf implements Runnable{
private Phones phones;
public PhoneXf(Phones phones){
this.phones = phones;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
phones.get();//調(diào)用消費(fèi)產(chǎn)品方法
}
}
}
/**
*產(chǎn)品的對(duì)象,生產(chǎn)的手機(jī)
*@author JEEP-711
*
*/
class Phones{
@Override
public String toString() {
return "Phones [name=" + name + ", content=" + content + "]";
}
private String name;
private String content;
/**true表示可以生產(chǎn),false表示可以消費(fèi)
*作為標(biāo)記,如何flag等于true表示可以生產(chǎn),如何flag等于false表示不可生產(chǎn)
*如果flag等于false表示可以消費(fèi)狀態(tài),可以取走,flag等于true表示不能取走
*解決重復(fù)值得問(wèn)題
*/
private boolean flag = true;//表示可以生產(chǎn),false表示可以消費(fèi)
//構(gòu)造方法
public Phones(String name, String content) {
super();
this.name = name;
this.content = content;
}
//取得名稱方法
public String getName() {
return name;
}
//設(shè)置名稱方法
public void setName(String name) {
this.name = name;
}
//取得內(nèi)容方法
public String getContent() {
return content;
}
//設(shè)置內(nèi)容方法
public void setContent(String content) {
this.content = content;
}
/**
*通過(guò)同步,解決了取值錯(cuò)誤問(wèn)題
*@param name
*@param content
*/
//生產(chǎn)制造同步方法
public synchronized void set(String name, String content){
if(!flag){
try {
//調(diào)用該方法,當(dāng)前線程進(jìn)入等待池等待狀態(tài),沒(méi)有指定時(shí)間,
//需要其他線程喚醒,釋放對(duì)象鎖,讓出cpu
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setContent(content);
flag = false;//表示可以消費(fèi),取走
this.notify();//喚醒在該監(jiān)視器上的一個(gè)線程
}
//消費(fèi)產(chǎn)品同步取值方法
public synchronized void get(){
if(flag){
try {
//調(diào)用該方法,當(dāng)前線程進(jìn)入等待池等待狀態(tài),沒(méi)有指定時(shí)間,
//需要其他線程喚醒,釋放對(duì)象鎖,讓出cpu
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+":"+this.getContent());
flag = true;
this.notify();
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: