對於單例模式面試官會怎樣提問呢?你又該如何回答呢?

前言

在面試的時候面試官會怎麼在單例模式中提問呢?你又該如何回答呢?可能你在面試的時候你會碰到這些問題:

  • 為什麼說餓漢式單例天生就是線程安全的?

  • 傳統的懶漢式單例為什麼是非線程安全的?

  • 怎麼修改傳統的懶漢式單例,使其線程變得安全?

  • 線程安全的單例的實現還有哪些,怎麼實現?

  • 雙重檢查模式、Volatile關鍵字 在單例模式中的應用

  • ThreadLocal 在單例模式中的應用

  • 枚舉式單例

那我們該怎麼回答呢?那答案來了,看完接下來的內容就可以跟面試官嘮嘮單例模式了

 

單例模式簡介

單例模式是一種常用的軟件設計模式,其屬於創建型模式,其含義即是一個類只有一個實例,併為整個系統提供一個全局訪問點 (向整個系統提供這個實)。

結構:

                      

單例模式三要素:

  • 私有的構造方法;

  • 私有靜態實例引用;

  • 返回靜態實例的靜態公有方法。

單例模式的優點

  • 在內存中只有一個對象,節省內存空間;

  • 避免頻繁的創建銷毀對象,可以提高性能;

  • 避免對共享資源的多重佔用,簡化訪問;

  • 為整個系統提供一個全局訪問點。

單例模式的注意事項

  在使用單例模式時,我們必須使用單例類提供的公有工廠方法得到單例對象,而不應該使用反射來創建,使用反射將會破壞單例模式 ,將會實例化一個新對象。

 

單線程實現方式

在單線程環境下,單例模式根據實例化對象時機的不同分為,

  • 餓漢式單例(立即加載)餓漢式單例在單例類被加載時候,就實例化一個對象並將引用所指向的這個實例;

  • 懶漢式單例(延遲加載),只有在需要使用的時候才會實例化一個對象將引用所指向的這個實例。

 

從速度和反應時間角度來講,餓漢式(又稱立即加載)要好一些;從資源利用效率上說,懶漢式(又稱延遲加載)要好一些。

餓漢式單例

// 餓漢式單例
public class HungrySingleton{
​
    // 私有靜態實例引用,創建私有靜態實例,並將引用所指向的實例
    private static HungrySingleton singleton = new HungrySingleton();
    // 私有的構造方法
    private HungrySingleton(){}
    //返回靜態實例的靜態公有方法,靜態工廠方法
    public static HungrySingleton getSingleton(){
        return singleton;
    }
}

餓漢式單例,在類被加載時,就會實例化一個對象並將引用所指向的這個實例;更重要的是,由於這個類在整個生命周期中只會被加載一次,只會被創建一次,因此惡漢式單例線程安全的。

那餓漢式單例為什麼是天生就線程安全呢?

因為類加載的方式是按需加載,且只加載一次。由於一個類在整個生命周期中只會被加載一次,在線程訪問單例對象之前就已經創建好了,且僅此一個實例。即線程每次都只能也必定只可以拿到這個唯一的對象。

懶漢式單例

// 懶漢式單例
public class LazySingleton {
    // 私有靜態實例引用
    private static LazySingleton singleton;
    // 私有的構造方法
    private LazySingleton(){}
    // 返回靜態實例的靜態公有方法,靜態工廠方法
    public static LazySingleton getSingleton(){
        //當需要創建類的時候創建單例類,並將引用所指向的實例
        if (singleton == null) {
            singleton = new LazySingleton();
        }
        return singleton;
    }
}

懶漢式單例是延遲加載,只有在需要使用的時候才會實例化一個對象,並將引用所指向的這個對象。

由於是需要時創建,在多線程環境是不安全的,可能會併發創建實例,出現多實例的情況,單例模式的初衷是相背離的。那我們需要怎麼避免呢?可以看接下來的多線程中單例模式的實現形式。

那為什麼傳統的懶漢式單例為什麼是非線程安全的?

非線程安全主要原因是,會有多個線程同時進入創建實例(if (singleton == null) {}代碼塊)的情況發生。當這種這種情形發生后,該單例類就會創建出多個實例,違背單例模式的初衷。因此,傳統的懶漢式單例是非線程安全的。

 

多線程實現方式

  在單線程環境下,無論是餓漢式單例還是懶漢式單例,它們都能夠正常工作。但是,在多線程環境下就有可能發生變異:

  • 餓漢式單例天生就是線程安全的,可以直接用於多線程而不會出現問題

  • 懶漢式單例本身是非線程安全的,因此就會出現多個實例的情況,與單例模式的初衷是相背離的。

 

那我們應該怎麼在懶漢的基礎上改造呢?

  • synchronized方法

  • synchronized塊

  • 使用內部類實現延遲加載

synchronized方法

// 線程安全的懶漢式單例
public class SynchronizedSingleton {
    private static SynchronizedSingleton synchronizedSingleton;
    private SynchronizedSingleton(){}
    // 使用 synchronized 修飾,臨界資源的同步互斥訪問
    public static synchronized SynchronizedSingleton getSingleton(){
        if (synchronizedSingleton == null) {
            synchronizedSingleton = new SynchronizedSingleton();
        }
        return synchronizedSingleton;
    }
}

  使用 synchronized 修飾 getSingleton()方法,將getSingleton()方法進行加鎖,實現對臨界資源的同步互斥訪問,以此來保證單例。

雖然可現實線程安全,但由於同步的作用域偏大、鎖的粒度有點粗,會導致運行效率會很低。

synchronized塊

// 線程安全的懶漢式單例
public class BlockSingleton {
    private static BlockSingleton singleton;
    private BlockSingleton(){}
    public static BlockSingleton getSingleton2(){
        synchronized(BlockSingleton.class){  // 使用 synchronized 塊,臨界資源的同步互斥訪問
            if (singleton == null) { 
                singleton = new BlockSingleton();
            }
        }
        return singleton;
    }
}

 其實synchronized塊跟synchronized方法類似,效率都偏低。

使用內部類實現延遲加載

// 線程安全的懶漢式單例
public class InsideSingleton {
    // 私有內部類,按需加載,用時加載,也就是延遲加載
    private static class Holder {
        private static InsideSingleton insideSingleton = new InsideSingleton();
    }
    private InsideSingleton() {
    }
    public static InsideSingleton getSingleton() {
        return Holder.insideSingleton;
    }
}
  • 如上述代碼所示,我們可以使用內部類實現線程安全的懶漢式單例,這種方式也是一種效率比較高的做法。其跟餓漢式單例原理是相同的, 但可能還存在反射攻擊或者反序列化攻擊 。

 

雙重檢查(Double-Check idiom)現實

雙重檢查(Double-Check idiom)-volatile

使用雙重檢測同步延遲加載去創建單例,不但保證了單例,而且提高了程序運行效率。

// 線程安全的懶漢式單例
public class DoubleCheckSingleton {
    //使用volatile關鍵字防止重排序,因為 new Instance()是一個非原子操作,可能創建一個不完整的實例
    private static volatile DoubleCheckSingleton singleton;
    private DoubleCheckSingleton() {
    }
​
    public static DoubleCheckSingleton getSingleton() {
        // Double-Check idiom
        if (singleton == null) {
            synchronized (DoubleCheckSingleton.class) {       
                // 只需在第一次創建實例時才同步
                if (singleton == null) {      
                    singleton = new DoubleCheckSingleton();      
                }
            }
        }
        return singleton;
    }
​
}

為了在保證單例的前提下提高運行效率,我們需要對singleton實例進行第二次檢查,為的式避開過多的同步(因為同步只需在第一次創建實例時才同步,一旦創建成功,以後獲取實例時就不需要同步獲取鎖了)。

但需要注意的必須使用volatile關鍵字修飾單例引用,為什麼呢?

 如果沒有使用volatile關鍵字是可能會導致指令重排序情況出現,在Singleton 構造函數體執行之前,變量 singleton可能提前成為非 null 的,即賦值語句在對象實例化之前調用,此時別的線程將得到的是一個不完整(未初始化)的對象,會導致系統崩潰。

此可能為程序執行步驟:

  1. 線程 1 進入 getSingleton() 方法,由於 singleton 為 null,線程 1 進入 synchronized 塊 ;

  2. 同樣由於 singleton為 null,線程 1 直接前進到 singleton = new DoubleCheckSingleton()處,在new對象的時候出現重排序,導致在構造函數執行之前,使實例成為非 null,並且該實例並未初始化的(原因在NOTE);

  3. 此時,線程 2 檢查實例是否為 null。由於實例不為 null,線程 2 得到一個不完整(未初始化)的 Singleton 對象

  4. 線程 1 通過運行 Singleton對象的構造函數來完成對該對象的初始化。

  這種安全隱患正是由於指令重排序的問題所導致的。而volatile 關鍵字正好可以完美解決了這個問題。使用volatile關鍵字修飾單例引用就可以避免上述災難。

NOTE

new 操作會進行三步走,預想中的執行步驟:

memory = allocate();        //1:分配對象的內存空間
ctorInstance(memory);       //2:初始化對象
singleton = memory;        //3:使singleton3指向剛分配的內存地址

**但實際上,這個過程可能發生無序寫入(指令重排序),可能會導致所下執行步驟:

memory = allocate();        //1:分配對象的內存空間
singleton3 = memory;        //3:使singleton3指向剛分配的內存地址
ctorInstance(memory);       //2:初始化對象

雙重檢查(Double-Check idiom)-ThreadLocal

  藉助於 ThreadLocal,我們可以實現雙重檢查模式的變體。我們將臨界資源線程局部化,具體到本例就是將雙重檢測的第一層檢測條件 if (instance == null) 轉換為 線程局部範圍內的操作 。

// 線程安全的懶漢式單例
public class ThreadLocalSingleton 
    // ThreadLocal 線程局部變量
    private static ThreadLocal<ThreadLocalSingleton> threadLocal = new ThreadLocal<ThreadLocalSingleton>();
    private static ThreadLocalSingleton singleton = null;
    private ThreadLocalSingleton(){}
    public static ThreadLocalSingleton getSingleton(){
        if (threadLocal.get() == null) {        // 第一次檢查:該線程是否第一次訪問
            createSingleton();
        }
        return singleton;
    }
​
    public static void createSingleton(){
        synchronized (ThreadLocalSingleton.class) {
            if (singleton == null) {          // 第二次檢查:該單例是否被創建
                singleton = new ThreadLocalSingleton();   // 只執行一次
            }
        }
        threadLocal.set(singleton);      // 將單例放入當前線程的局部變量中 
    }
}

藉助於 ThreadLocal,我們也可以實現線程安全的懶漢式單例。但與直接雙重檢查模式使用,使用ThreadLocal的實現在效率上還不如雙重檢查鎖定。

 

枚舉實現方式

它不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象,

直接通過Singleton.INSTANCE.whateverMethod()的方式調用即可。方便、簡潔又安全。

public enum EnumSingleton {
    instance;
    public void whateverMethod(){
        //dosomething
    }
}

 

 

測試單例線程安全性

 使用多個線程,並使用hashCode值計算每個實例的值,值相同為同一實例,否則為不同實例。

public class Test {
    public static void main(String[] args) {
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new TestThread();
​
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
​
        }
    }
}
class TestThread extends Thread {
    @Override
    public void run() {
        // 對於不同單例模式的實現,只需更改相應的單例類名及其公有靜態工廠方法名即可
        int hash = Singleton5.getSingleton5().hashCode();  
        System.out.println(hash);
    }
}

 

 

小結

單例模式是 Java 中最簡單,也是最基礎,最常用的設計模式之一。在運行期間,保證某個類只創建一個實例,保證一個類僅有一個實例,並提供一個訪問它的全局訪問點 ,介紹單例模式的各種寫法:

  • 餓漢式單例(線程安全)

  • 懶漢式單例

    • 傳統懶漢式單例(線程安全);

    • 使用synchronized方法實(線程安全);

    • 使用synchronized塊實現懶漢式單例(線程安全);

    • 使用靜態內部類實現懶漢式單例(線程安全)。

  • 使用雙重檢查模式

    • 使用volatile關鍵字(線程安全);

    • 使用ThreadLocal實現懶漢式單例(線程安全)。

  • 枚舉式單例

 

各位看官還可以嗎?喜歡的話,動動手指點個,點個關注唄!!謝謝支持! 歡迎關注公眾號【Ccww技術博客】,原創技術文章第一時間推出

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※回頭車貨運收費標準

台中搬家公司費用怎麼算?

奧運再生能源準備不延期 東京主場館的透明太陽能板 滋養草坪又能發電

文:宋瑞文(加州能源特約撰述)

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

美國人忙抗疫 川普悄悄對環境政策上下其手

環境資訊中心外電;姜唯 翻譯;林大利 審校;稿源:ENS

非營利組織「西部優先中心(Center for Western Priorities)」發現,過去一個月,美國人忙著與新冠病毒作戰,川普的內政部一邊悄悄影響環境相關政策制定。自川普簽署第一份緊急新冠病毒法案後一個月,內政部啟動數十項與武漢肺炎(COVID-19)無關的政策行動,取消瀕危野生動植物保護法令,並在全國各地擴大辦理採礦和油氣租約銷售。

西部優先中心列出3月6日川普簽署首份新冠病毒緊急法案後,內政部採取的57項行動,像是34個民意徵詢期被啟動或結束,儘管地方民代和國會多次要求內政部長大衛.伯恩哈特(David Bernhardt)在疫情期間暫停立法程序。

西部優先中心列出3月6日川普簽署首份新冠病毒緊急法案後,內政部採取的57項行動。照片來源:Gage Skidmore(CC BY-SA 2.0)

「美國忙著應付全球性傳染病,但伯恩哈特可沒有忘記油氣和採礦公司付了他多年薪水、交付給他的使命。」西部優先中心執行董事羅卡拉(Jennifer Rokala)說,「看看他在新冠病毒危機惡化時做的事,他拒絕關閉國家公園、無視這對國家公園管理員帶來的危險,也是不意外。」

3月6日以來,美國內政部已完成至少九項對公共和部落土地有永久性影響的行動,包括擴大亞利桑那州和內華達州的硬岩採礦業務,以及撤回麻薩諸塞州Mashpee Wampanoag部落的信託土地。

Mashpee Wampanoag部落在該地區生活超過1萬2000年。由於內政部下印地安事務局的決策,該部落很可能會失去僅存的家園。這個決策嚴重打擊部落主權,影響部落未來和永續性。該部落正在要求國會保護其保留土地,並提出《馬什皮.旺帕諾格部落保留法案》(H.R.312)。

美國內政部還針對《瀕危物種法》,提出削弱弓背鮭(Gila cypha)和波多黎各蘭花保育工作的政策,並取消了北美松雞(Centrocercus urophasianus)保育提案。

儘管石油生產過剩導致全球石油價格暴跌,但美國內政部3月份仍舉行了七次油氣租約銷售。

儘管疫情導致煤炭暫停生產、礦場關閉,煤炭需求也大減,美國內政部仍宣布4月將在科羅拉多州舉行煤炭租約銷售活動。

3月27日,內政部核准在阿拉斯加修建一條會穿過北極門國家公園保護區的私人採礦道路。伯恩哈特之前任職的法律事務所,正是該道路所屬加拿大礦業公司Trilogy Metals的遊說代表。

3月27日,內政部核准在阿拉斯加修建一條會穿過北極門國家公園保護區的私人採礦道路。照片來源:
維基百科/美國漁業與野生動物局

此外,伯恩哈特還拒絕展延第一份新冠病毒法案簽署前,才剛剛開啟的幾個重要民意徵詢期,其中有爭議性的計畫,核准在新墨西哥州查科文化國家歷史公園附近的鑽探活動。新墨西哥州國會代表團和自然保護組織已呼籲伯恩哈特延長民意徵詢期。

內政部土地管理局(Bureau of Land Management)僅在4月6日展延了一個民意徵詢期,讓公眾可以在5月21日之前對影響整個西部北美松雞棲地的六份環境影響聲明草案發表評論。

除了內政部的57項行動之外,美國行政管理和預算局(Office of Management and Budget, OBM)還繼續與油氣公司舉行會議,討論內政部未來的法規制定問題。

3月18日,OMB和內政部官員會見了殼牌、埃克森美孚、康菲石油公司和美國石油學會代表,討論油氣和煤炭公司支付納稅人特許權使用費時,如何對鑽取自公有土地上的產品估價。 

川普政府於2017年試圖廢除歐巴馬時代訂定的法規。該法規關閉了一個漏洞,不再讓企業以低於市價的價格賣煤炭給自己。最後因法院阻止而沒有廢除成功。

Trump Erodes Eco-Protections as Americans Die of Virus DENVER, Colorado, April 7, 2020 (ENS)

As America fought the new coronavirus over the past 30 days, President Donald Trump’s Interior Department rushed through dozens of attacks on the environment, finds a new analysis by the nonprofit Center for Western Priorities. In the month since Trump signed the first emergency coronavirus bill, the Interior Department has taken dozens of policy actions unrelated to COVID-19, removing protections for endangered wildlife, plus expanding mining operations and oil and gas leasing on public lands across the country.

The Center for Western Priorities’ analysis identified 57 separate actions taken by Interior Department agencies since March 6, when President Trump signed the first coronavirus emergency bill.

Those actions include 34 public comment periods that were opened or closed by the Interior Department despite numerous requests from local elected officials and members of Congress that Interior Secretary David Bernhardt suspend rulemakings during the coronavirus pandemic.

“While the country was focused on slowing a global pandemic, Secretary Bernhardt did not lose sight of his singular mission to deliver favors for the oil, gas, and mining companies that paid his salary for years,” commented Jennifer Rokala, executive director at the Center for Western Priorities.

“When you look at the audacious scope of what he was doing as the coronavirus crisis accelerated, it’s no wonder he was so blind to the risk that he created for America’s park rangers by refusing to close park gates,” Rokala said.

Since March 6, Interior has finalized at least nine actions that will have lasting effects on public and tribal lands, including expansions of hardrock mining operations in Arizona and Nevada, and the revocation of tribal trust lands from the Mashpee Wampanoag Tribe in Massachusetts.

The Mashpee Wampanoag have occupied the same region for over 12,000 years. The very tribe that welcomed the Pilgrims in the 1600s is at risk of losing what is left of their homelands due to a determination made by the Bureau of Indian Affairs, a part of the Interior Department.

The decision is a blow to tribal sovereignty and undermines the future and sustainability of the tribal nation. In response, the tribe is asking Congress to protect its reservation lands and has proposed the Mashpee Wampanoag Tribe Reservation Reaffirmation Act (H.R.312).

The Department of the Interior also continued its efforts to undermine the Endangered Species Act, advancing policies that would reduce protections for the humpback chub fish and a Puerto Rican orchid, and eliminating a proposal that would have established protections for the sage-grouse.

In March, the Interior Department held seven oil and gas lease sales, despite a glut of oil production leading to the collapse of global oil prices.

Interior also announced an April coal lease sale in Colorado despite falling coal production and mine closures due to the risk of COVID-19, the dearly respiratory disease caused by the novel coronavirus, as well as low demand for coal.

On March 27, the agency paved the way for a private mining road to be built through Gates of the Arctic National Preserve in Alaska.

Secretary Bernhardt’s former lobbying and law firm, Brownstein Hyatt Farber Schreck, has lobbied the Interior Department to approve the project on behalf of the Canadian mining corporation Trilogy Metals, based in Vancouver.

In addition to the 32 public comment periods opened or closed since March 6, Secretary Bernhardt has refused to extend several key comment periods that opened just prior to the president’s signature on the first coronavirus bill. This includes the controversial plan to allow additional drilling near New Mexico’s Chaco Culture National Historic Park.

New Mexico’s congressional delegation and conservation groups have urged Bernhardt to extend the window for public comment, which opened on February 28th.

The Bureau of Land Management did extend one comment period on April 6, giving the public until May 21 to comment on six draft environmental impact statements that affect sage-grouse habitat across the West.

In addition to the 57 actions taken by the Interior Department, the White House Office of Management and Budget, OMB, also continued to hold meetings with oil and gas companies regarding future rulemakings by the Interior Department.

On March 18, OMB and Interior officials met with representatives of Shell, ExxonMobil, ConocoPhillips, and the American Petroleum Institute regarding a proposed rule on how oil, gas, and coal companies are allowed to value products extracted from public land when paying royalties to taxpayers.

The Trump administration in 2017 attempted to repeal an Obama-era rule that closed a loophole allowing companies to essentially sell coal to themselves at below-market prices, but that repeal was blocked by the courts.

※ 全文及圖片詳見:ENS

環境政策
動物與大環境變遷
武漢肺炎
國際新聞
美國
全球變遷
氣候變遷

作者

姜唯

如果有一件事是重要的,如果能為孩子實現一個願望,那就是人類與大自然和諧共存。

林大利

於特有生物研究保育中心服務,小鳥和棲地是主要的研究對象。是龜毛的讀者,認為龜毛是探索世界的美德。

延伸閱讀

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

網頁設計最專業,超強功能平台可客製化

學者:野火致觀光客減少 有助控制澳洲疫情

摘錄自2020年4月13日中央社報導

一位澳洲學者說,幾個月前的森林大火雖然造成重大傷亡和損失,但減少可能染疫的觀光客到訪,意外地降低2019新型冠狀病毒(COVID-19,武漢肺炎)疫情對澳洲的衝擊。

澳洲國立大學傳染病教授柯里諾(Peter Collignon)說,要是沒有這場災難,澳洲的新型冠狀病毒疫情恐怕一發不可收拾。澳洲觀光及交通業界論壇組織(Tourism and Transport Forum)執行長奧斯蒙(Margy Osmond)表示,早在武漢肺炎疫情爆發之前,澳洲觀光業本就因為森林大火而受到重創。

澳洲衛生部最新的數據顯示,截至澳洲東部標準時間(AEST)13日下午3時止,澳洲2019冠狀病毒疾病確診病例24小時內增加46例,累計達6359例,其中61人死亡。確診人數最多的新南威爾斯州有2863個病例,約占45%。全國有36萬2000多人已接受病毒檢測。

生活環境
國際新聞
澳洲
澳洲野火
地方觀光
控制疫情
武漢肺炎
動物與大環境變遷

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計最專業,超強功能平台可客製化

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※回頭車貨運收費標準

※推薦評價好的iphone維修中心

※教你寫出一流的銷售文案?

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

台中搬家公司費用怎麼算?

中國傳統市場照賣 澳:全球健康威脅

摘錄自2020年4月15日自由時報報導

武漢肺炎疫情被認為起源自中國傳統市場販售的野味,最早傳出疫情的武漢市華南海鮮批發市場目前仍被關閉。但另一個武漢市最大的傳統市場「白沙洲大市場」,不僅在封城期間維持基本的運作,解封後也很快就恢復疫情爆發前的熱絡景況。

為防堵疫情因市場活動二度爆發,民眾必須持有健康認證「綠碼」、量測體溫後才能進入白沙洲大市場,載貨的車輛也需經過消毒。白沙洲大市場販賣蔬菜、魚貨、冷藏雞肉與當季食品,當地攤販指出,該市場禁止宰殺雞、豬、羊等家禽畜,必須在專門的屠宰場完成宰殺後,再送至市場販賣。

澳洲總理莫里森14日指出,他難以理解世衛組織竟坐視中國的傳統市場繼續營運,並表示這不是第一次出現源自市場的病毒,稱傳統市場為「全球健康威脅」。

但世衛組織上週表示,傳統市場為中國人民重要的收入與食物來源,不支持中國關閉所有傳統市場,且中國目前只允許傳統市場銷售安全的食物,衛生水準已經提升。世衛組織特使納巴羅也於14日受訪時說,為防止下一次的全球大流行,世衛組織建議各國應該關閉「危險的」傳統市場,但也強調,世衛組織無法強制任何國家關閉市場。

生活環境
國際新聞
中國新聞
中國
武漢
傳統市場
食品安全

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※回頭車貨運收費標準

※推薦評價好的iphone維修中心

※超省錢租車方案

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

※推薦台中搬家公司優質服務,可到府估價

仰賴自然卻摧毀自然 珍古德:導致病毒大爆發

摘錄自2020年4月14日自由時報報導

世界著名的英國靈長類動物學家珍古德(Jane Goodall)11日於電話訪談中指出,武漢肺炎(COVID-19)的大爆發是由於人類長期以來對自然的漠視和對動物的不尊重。

《法新社》報導,珍古德認為,病毒的大流行從很久以前就被預言了。以砍伐森林為例,動物棲地減少,不同物種被迫靠近,因而互相傳染疾病,久之,當生活空間少到牠們不得已向人類居住地接近時,人類便被傳染。她補充:「當然,野生動物的捕食也是原因之一,特別是中國和非洲。」

她進一步表示,中國禁止野生動物市場是一件好事,「希望是永久性的」,且期待亞洲其他國家能夠跟進。但珍古德也明白,在非洲會相對難以實施該禁令,因為許多民眾賴以為生,「當人們沒有其他管道養活自己和家人時,你不可能直接禁止他做(野生動物買賣)。」

土地水文
土地利用
國際新聞
珍古德
冠狀病毒
災害

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※回頭車貨運收費標準

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※推薦評價好的iphone維修中心

※教你寫出一流的銷售文案?

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

殼牌石油拚減碳 誓言最遲2050年達零排放

摘錄自2020年4月16日聯合報報導

國際石油天然氣巨擘荷蘭皇家殼牌集團(Royal Dutch Shell)今(16日)誓言,在2050年前要達成「碳中和」(Carbon Neutral)目標,和競爭對手英國石油公司(BP)的承諾一樣。

法新社報導,殼牌執行長范柏登(Ben vanBeurden)在聲明中表示,社會對於氣候變遷的期許瞬息萬變,殼牌需要再進一步自我要求,計畫最晚在2050年成為零排放的能源企業。殼牌將在2050年前把自家能源產品的「淨碳足跡」減少約65%;在2030年減少30%。

溫室氣體
能源議題
全球變遷
氣候變遷
能源轉型
國際新聞
殼牌
減碳宣言
零排放
石油

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

日本大鯢數量急減 雜交問題嚴重 水族館推大鯢布偶提升國民關注

文:宋瑞文

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

※回頭車貨運收費標準

CentOS8.1中使用通用二進制包安裝MySQL8.0

  寫在前的的話: 在IT技術日新月異的今天,老司機也可能在看似熟悉的道路上翻車,甚至是大型翻車現場!自己一個人開車過去翻個車不可怕,可怕的是帶着整個團隊甚至是整個公司一起翻車山崖下,解決辦法就是:新出現的道路自己先過一遍,留好坑位標記,將來帶隊過去時不再翻車!!!

 

  最近剛好在進行權限系統的微服務化改造,要重新搭一套開發服務器環境。今天搭的是MySQL數據庫服務器,MySQL 8.0出來也有些年月了,現在(2020)大多數公司還沒在生產上用上,於是乎就想嘗個鮮,選擇了在CentOS8.1上進行MySQL8.0服務器的搭建。當前來說CentOS8.1也算比較新了!

 

  老樣子,先裝一個全新的CentOS8.1虛擬機,選擇裝配基本的Server軟件包,網絡模式選擇【橋接模式(自動)】(主要為了讓宿主機和虛擬機的網絡處於等級),IP地址相關信息切記選擇手工配置,不能用DHCP進行動態分配(有DNS服務器輔助除外),為什麼呢?因為你是在配服務器,IP地址要固定下來,不然每次啟動后的IP都不同,那就很尷尬了!

 

  服務器操作系統準備好后該去下載MySQL8.0了,去哪裡下呢?當然是MySQL8.0社區版官網!可是跑到網官一看,估計有些同學就一臉懵逼,純英文的不說,安裝包還各樣種樣的!怎麼選呢?

  首先要選定操作系統平台,我這邊是CentOS8.1 x86_64位架構,那我要選Linux版本的,最好是CentOS專用的!結果找了一圈暫時還沒有CentOS專用的版本(RedHat專用版本到是有,其實我們知道CentOS是就源自RedHat)…為了保險起見,我們選Linux通用版(Linux-Generic),結果出來的列表也不少!這麼多都是些啥,見圖標解吧:

 

  我選擇【64位通用二進制最小安裝壓縮包(不含調試組件及調式符號)】,理由:

  1. 我的目標操作系統是64位的CentOS;
  2. 我不需要做MySQL的調試;
  3. CentOS8.1上帶有專用的解壓安裝工具tar;
  4. 小包從官網下載和上傳到服務器都快(MySQL數據庫功能也完整,別看小了那麼多!);

  點擊Download后出現的界面中會建議你登錄你的Oracle Web賬號,不用登錄(當然你有賬號也可以登錄),直接點下面的一小行字——“No thanks,just start my download.

 

  將目標包(mysql-8.0.20-linux-x86_64-minimal.tar.xz)下載好后,使用SecureCRT上傳到服務器 /opt 目錄下!(Linux眾多目錄的作用)

  接下來開始正式安裝MySQL8.0,記住我們的前提是:全新的、乾淨的CentOS8.1操作系統,之前沒有裝過MySQL的!如果之前裝過MySQL是要先把相關目錄和配置文件刪除乾淨才能再裝的!謹記!謹記!謹記!

  第一步:使用yum包管理器檢查並安裝異步IO依賴包 libaio ,如果沒裝這個包,數據目錄初始化和後續服務器的啟動都將失敗,如果檢查發現沒裝,要將它裝上:

# yum search libaio 
# yum -y install libaio 

  第二步:由於CentOS是源自RedHat的,而RedHat系列的操作系統中沒有MySQL通用二進制安裝包(不管有沒有壓縮)中的MySQL客戶端(bin/mysql)組件所需要的 /lib64/libtinfo.so.5 文件,為了解決這個問題,需要安裝一個含有該文件的 ncurses-compat-libs 包(截圖是已經裝過一次的結果):

# yum -y install ncurses-compat-libs

  第三步:轉到 mysql-8.0.20-linux-x86_64-minimal.tar.xz 壓縮包存放目錄 /opt ,使用 tar 命令進行解壓(直接解壓到當前目錄):

# cd /opt
# tar -xvf mysql-8.0.20-linux-x86_64-minimal.tar.xz

  解壓得到一個新目錄:/opt/mysql-8.0.20-linux-x86_64-minimal ,該目錄即為MySQL的真實安裝目錄

  第四步:創建用於運行MySQL的組和普通用戶(非操作系統用戶):

# groupadd mysql
# useradd -r -g mysql -s /bin/false mysql

  第五步:在用戶手動安裝軟件推薦安裝目錄 /usr/local 中創建MySQL的真實安裝目錄的軟鏈接目錄(軟鏈接目錄不能是已經存在的目錄,相當於Windows快捷方式):

# cd /usr/local
# ln -s /opt/mysql-8.0.20-linux-x86_64-minimal mysql

  第六步:在mysql軟鏈接目錄中創建導入導出操作安全目錄(該目錄用於使具有FILE權限的用戶可以安全地執行導入導出操作):

# cd /usr/local/mysql
# mkdir mysql-files
# chown mysql:mysql mysql-files
# chmod 750 mysql-files

  (其實,第六步做完后就已經有辦法可以臨時點亮MySQL服務器了,這裏不講,因為我們要配的是一個長期運行的MySQL數據庫服務器)

  第七步:在mysql軟鏈接目錄下創建數據目錄:

# cd /usr/local/mysql
# mkdir data
# chown mysql:mysql data
# chmod 750 data

  第八步:創建MySQL服務啟動需要用到的靜態配置文件(如果目錄下已經有了同名文件,則需要換一個名字,之前沒裝過MySQL一般是不會有的!):

# cd /etc
# touch my.cnf
# chown root:root my.cnf
# chmod 644 my.cnf

  第九步:使用vi或vim打開第八步創建的配置文件 /etc/my.cnf ,加入MySQL服務的配置信息

[mysqld]
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
port=3306
log-error=/usr/local/mysql/data/mysqldb.xgclassroom.err
user=mysql
secure_file_priv=/usr/local/mysql/mysql-files
local_infile=OFF

  注意:配置中log-error的值一般中根據你安裝操作系統時設置的Host名稱相關,大家的不一樣,當然你也可以直接指定新名字!

  另外,如果要InnoDB的相關配置項,那麼只能在數據目錄初始化(第十步)之前在my.cnf中進行配置,主要有 innodb_data_home_dir,innodb_data_file_path,,innodb_log_file_size,innodb_log_group_home_dir 和 innodb_page_size 這幾項,未配置的情況下,它們都使用默認值。

  第十步:初始化第七步創建的數據目錄(因為要用到第八和第九步創建的配置文件)

# cd /usr/local/mysql
# bin/mysqld --defaults-file=/etc/my.cnf --initialize

  注意:數據目錄初始化成功后,會在第九步所設置的log-error日誌文件(我的是 /usr/local/mysql/data/mysqldb.xgclassroom.err)中生成 root@localhost 的初始密碼(賬號冒號後面的QdbB=9e!lT6=就是,要記住這個初始密碼,後面登錄root賬號是要它來修改初始密碼),類似下面的信息(可以使用cat命令查看):

...省略...
A temporary password is generated for root@localhost: yi5w%J*hws6E
...省略...

  現在我們還缺了最最最重要的一項配置——讓MySQL服務隨操作系統的啟動自動啟動!繼續配置ing!

  在Linux系統中目前系統服務主要以 systemd 服務單元的形式存在(類似windows平台的services.msc下管理的各個服務),Linux系統下一切皆文件,systemd 服務單元也是由一個個systemd 服務單元配置文件組成,systemd 服務單元配置文件 = systemd 服務單元!配置文件名就是服務單元名!所有服務單元的配置文件統一放在 /usr/lib/systemd/system 目錄下。

  第十一步:在系統服務單元配置文件存放目下創建MySQL的服務單元配置文件:

# cd /usr/lib/systemd/system
# touch mysqld.service
# chmod 644 mysqld.service

  第十二步:使用vi或vim打開第十一步創建的MySQL服務單元配置文件 /usr/lib/systemd/system/mysqld.service,並加入MySQL服務單元配置信息:

[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql

# Have mysqld write its state to the systemd notify socket
Type=notify

# Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=0

# Start main service
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf $MYSQLD_OPTS 

# Use this to switch malloc implementation
EnvironmentFile=-/etc/sysconfig/mysql

# Sets open_files_limit
LimitNOFILE = 10000

Restart=on-failure

RestartPreventExitStatus=1

# Set environment variable MYSQLD_PARENT_PID. This is required for restart.
Environment=MYSQLD_PARENT_PID=1

PrivateTmp=false

  第十三步:啟用MySQL服務單元配置

# systemctl enable mysqld.service

  經過上面的一系列安裝和配置步驟后,此時我們已經可以通過systemctl工具手工管理MySQL服務了:

# systemctl {start|stop|restart|status} mysqld

  第十四步:啟動MySQL服務,並查看MySQL服務狀態:

# systemctl start mysqld
# systemctl status mysqld

  第十五步:重啟服務器,檢驗MySQL服務是否隨服務器一起啟動了:

# reboot

  …重啟系統中…

# systemctl status mysqld

  如果最終MySQL服務狀態正常,那麼CentOS8.1上MySQL8.0的安裝就算是完成了,但是不要高興的太早了!還有好多事要做:

  1、將服務器上的MySQL客戶端(bin/mysql)配置到系統環境變量PATH中:

  如果不將MySQL客戶端(bin/mysql)配到環境變量中,你會發現即使MySQL服務在正常運行,但直接在系統終端輸入mysql是找不到該命令的:

[root@mysqldb /]# mysql
-bash: mysql: command not found

  當然,你用完整MySQL客戶端(bin/mysql)命令路徑是可以運行該命令的(雖然報錯,但那表示命令可以使用了):

[root@mysqldb /]# /usr/local/mysql/bin/mysql
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

  系統環境變量PATH在環境變量配置文件 /etc/profile 中配置:

# vim /etc/profile

在文件的最後新起一行,插入:

export PATH=$PATH:/usr/local/mysql/bin

保存退出后,使用下面的命令手動使修改生效:

# source /etc/profile

  現在你可以直接在任意目錄下執行mysql命令了:

[root@mysqldb /]# mysql
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

  

  2、root賬號初始密碼修改:

  使用root初始密碼(記錄在第九步所設置的log-error日誌文件)登錄MySQL,並修改密碼:

[root@mysqldb /]# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.20

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>alter user 'root'@'localhost' identified by '1qaz@WSX';

 Query OK, 0 rows affected (0.00 sec)

 

  3、進行root賬號的服務器本機登錄測試:

  修改完root的默認密碼后,退出MySQL並使用新密碼重新嘗試登錄:

mysql> exit
Bye
[root@mysqldb /]# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

 

  4、對MySQL使用的端口號進行防火牆例外設置:

  先用root賬號登錄MySQL,檢查一下當前正在使用的端口號:

mysql> show global variables like 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port          | 3306  |
+---------------+-------+
1 row in set (0.01 sec)

  將目標端口號(例中為3306)添加到防火牆例外列表,並重新載入防火牆

# firewall-cmd --zone=public --add-port=3306/tcp --permanent
success
# firewall-cmd --reload
success

  注意1:一定要帶上–permanent 參數才能永遠生效,否則系統重啟后丟失,另外 –zone 、–add-port 和 –permanent參數前面是兩個-;

  注意2:一定要重新載入防火牆,讓設置生效;

 

  5、創建遠程登錄和使用MySQL的普通用戶(因為安全起見,root賬號一般不要設置成可以遠程登錄,要設置也盡量設置成只可在固定的某個IP遠程登錄):

  以root賬號登錄MySQL,使用以下SQL命令創建一個可以任意網絡互通的點登錄的賬號xurm 密碼 1qaz@WSX

create user xurm IDENTIFIED with mysql_native_password by '1qaz@WSX' account unlock;
select host,user from user;
grant all on *.* to xurm WITH GRANT OPTION;
FLUSH PRIVILEGES;

 

  認認真真上邊的步驟和細節進行安裝和配置后,現在可以從開發機的客戶端,用普通賬號登錄遠程MySQL服務器就可以愉快的玩耍了:

 

  以下記錄一次手賤導致的翻車現場:

  使用 # systemctl stop mysqld.service 成功關閉mysql服務后,嘗試直接使用 /usr/local/mysql/bin/mysqld 嘗試啟動mysql造成的後果:bin/mysqld 嘗試啟動時覆蓋並破壞了第十步數據目錄初始生成的有關文件,導至MySQL無法啟動,這時嘗試使用 # systemctl start mysqld.service也無法再啟動MySQL服務~~~

....
2020-06-06T04:38:39.614356Z 1 [ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
2020-06-06T04:38:40.618323Z 1 [ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
2020-06-06T04:38:41.619650Z 1 [ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
2020-06-06T04:38:41.620710Z 1 [ERROR] [MY-012592] [InnoDB] Operating system error number 11 in a file operation.
2020-06-06T04:38:41.621045Z 1 [ERROR] [MY-012596] [InnoDB] Error number 11 means 'Resource temporarily unavailable'
2020-06-06T04:38:41.621712Z 1 [ERROR] [MY-012215] [InnoDB] Cannot open datafile './ibdata1'
2020-06-06T04:38:41.622047Z 1 [ERROR] [MY-012959] [InnoDB] Could not open or create the system tablespace. 
If you tried to add new data files to the system tablespace, and it failed here, you should now edit innodb_data_file_path in my.cnf back to
what it was, and remove the new ibdata files InnoDB created in this failed attempt. InnoDB only wrote those files full of zeros, but did not
yet use them in any way. But be careful: do not remove old data files which contain your precious data!
2020-06-06T04:38:41.622372Z 1 [ERROR] [MY-012930] [InnoDB] Plugin initialization aborted with error Cannot open a file. 2020-06-06T04:38:42.119489Z 1 [ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine 2020-06-06T04:38:42.122437Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. 2020-06-06T04:38:42.127147Z 0 [ERROR] [MY-010119] [Server] Aborting 2020-06-06T04:38:42.127857Z 0 [System] [MY-010910] [Server] /usr/local/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.20) MySQL Community Server - GPL.

  提示信息中讓我在/etc/my.cnf配置文件中將 innodb_data_file_path 配置項的值改回原來的去,實際上我並沒有在/etc/my.cnf配置文件配置該項,而是一直使用着默認的 innodb_data_file_path 配置;

  提示信息讓我刪除啟動失敗的嘗試中InnoDB生成的新ibdata相關文件,講真的,因為一開始沒有對比過data/目錄中的文件,現在我都不知道哪些是InnoDB生成的新ibdata相關文件;

  最後想了一下,我是剛剛安裝的數據庫系統,也還沒有重要數據在上邊,現在data/目錄遭到破壞,那最快的辦法就是清空data/目錄,並重新初始化它,應該就能解決問題了(已經運行了段時間的生產數據庫千萬不要這麼玩,要備份好所有數據文件,否則會死得很難看!!!最好另尋它法,最最最好就不要讓這樣的車禍出現!):

  • 清空data/目錄:
#  rm -rf /usr/local/mysql/data/*

 

  • 使用第十步中的命令重新初始化數據目錄:
# cd /usr/local/mysql
# bin/mysqld --defaults-file=/etc/my.cnf --initialize

注意:數據目錄重新初始化成功后,會在第九步所設置的log-error日誌文件(我的是 /usr/local/mysql/data/mysqldb.xgclassroom.err)中生成新的 root@localhost 的初始密碼

 

  • 重啟嘗試啟動MySQL服務:
# systemctl start mysqld
Job for mysqld.service failed because the control process exited with error code.
See "systemctl status mysqld.service" and "journalctl -xe" for details.

  哦呵…又雙叒叕翻車了,重啟失敗!!! 慌得一逼!繼續…

 

  • 查看一下日誌文件/usr/local/mysql/data/mysqldb.xgclassroom.err
# cat mysqldb.xgclassroom.err 
2020-06-06T05:31:31.249888Z 0 [System] [MY-013169] [Server] /opt/mysql-8.0.20-linux-x86_64-minimal/bin/mysqld (mysqld 8.0.20) initializing of server in progress as process 2662
2020-06-06T05:31:31.256260Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2020-06-06T05:31:31.509465Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2020-06-06T05:31:31.995068Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: iqaaJCdnj3&e
2020-06-06T05:33:09.978908Z 0 [System] [MY-010116] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.0.20) starting as process 2714
2020-06-06T05:33:09.987836Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2020-06-06T05:33:10.212686Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2020-06-06T05:33:11.314035Z 0 [ERROR] [MY-011292] [Server] Plugin mysqlx reported: 'Preparation of I/O interfaces failed, X Protocol won't be accessible'
2020-06-06T05:33:11.314175Z 0 [ERROR] [MY-011300] [Server] Plugin mysqlx reported: 'Setup of bind-address: '*' port: 33060 failed, `bind()` 
failed with error: Address already in use (98). Do you already have another mysqld server running with Mysqlx ?' 2020-06-06T05:33:11.314342Z 0 [ERROR] [MY-011300] [Server] Plugin mysqlx reported: 'Setup of socket: '/tmp/mysqlx.sock' failed,
another process with PID 1734 is using UNIX socket file' 2020-06-06T05:33:11.413373Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. 2020-06-06T05:33:11.414505Z 0 [ERROR] [MY-010262] [Server] Can't start server: Bind on TCP/IP port: Address already in use 2020-06-06T05:33:11.414625Z 0 [ERROR] [MY-010257] [Server] Do you already have another mysqld server running on port: 3306 ? 2020-06-06T05:33:11.414918Z 0 [ERROR] [MY-010119] [Server] Aborting 2020-06-06T05:33:12.939872Z 0 [System] [MY-010910] [Server] /usr/local/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.20) MySQL Community Server - GPL.

  有個PID為1734的進程在佔用3306和33060端口?而且還可能是另一個mysqld server,我造,不會是真的吧!使用# systemctl status mysqld 都查過了,沒有服務了~

 

  • 查看一下3306端口的佔用情況先:
# netstat -anp | grep 3306
tcp6       0      0 :::33060                :::*                    LISTEN      1734/mysqld         
tcp6       0      0 :::3306                 :::*                    LISTEN      1734/mysqld 

  竟然真的有個mysqld進程(PID=1734)以tpc6的協議模式佔著3306和33060端口~

 

  • 查看一下這個mysqld進程的詳情,看看它是是哪裡來的:
# ps -aux | grep mysqld
mysql      1734  0.5 19.0 1773244 352616 ?      Sl   12:12   0:29 /usr/local/mysql/bin/mysqld
root       2786  0.0  0.0  12108  1080 pts/1    S+   13:45   0:00 grep --color=auto mysqld

  果然是手賤作的孽,直接通過/usr/local/mysql/bin/mysqld手動啟動的服務沒關徹底…

 

  • 幹掉佔用3306和33060端口的無效mysqld進程:
# kill -9 1734

 

  • 再次使用# systemctl start mysqld 命令啟動mysql:
# systemctl start mysqld
# systemctl status mysqld
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2020-06-06 13:47:15 CST; 20s ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
 Main PID: 2795 (mysqld)
   Status: "Server is operational"
    Tasks: 39 (limit: 11337)
   Memory: 327.7M
   CGroup: /system.slice/mysqld.service
           └─2795 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf

Jun 06 13:47:14 mysqldb.xgclassroom systemd[1]: Starting MySQL Server...
Jun 06 13:47:15 mysqldb.xgclassroom systemd[1]: Started MySQL Server.

 

  終於把車開回正路來了!!!使用日誌文件/usr/local/mysql/data/mysqldb.xgclassroom.err中記錄的新的初始密碼登錄mysql並修改初始化密碼就可以了!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

卷積生成對抗網絡(DCGAN)—生成手寫数字

深度卷積生成對抗網絡(DCGAN)

—- 生成 MNIST 手寫圖片

1、基本原理

生成對抗網絡(GAN)由2個重要的部分構成:

  • 生成器(Generator):通過機器生成數據(大部分情況下是圖像),目的是“騙過”判別器
  • 判別器(Discriminator):判斷這張圖像是真實的還是機器生成的,目的是找出生成器做的“假數據”

訓練過程

  • 1、固定判別器,讓生成器不斷生成假數據,給判別器判別,開始生成器很弱,但是隨着不斷的訓練,生成器不斷提升,最終騙過判別器。此時判別器判斷假數據的概率為50%
  • 2、固定生成器,訓練判別器。判別器經過訓練,提高鑒別能力,最終能準確判斷雖有的假圖片
  • 3、循環上兩個階段,最終生成器和判別器都越來越強。然後就可以使用生成器來生成我們想要的圖片了

2、相關數學原理

  • 判別器在這裡是一種分類器,用於區分樣本的真偽,因此我們常常使用交叉熵(cross entropy)來進行判別分佈的相似性

\[H(p, q) := -\sum_i p_i \log q_i \]

公式中 \(p_i\)\(q_i\) 為真實的樣本分佈和生成器的生成分佈

假定 \(y_1\) 為正確樣本分佈,那麼對應的( \(1-y_1\) )就是生成樣本的分佈。\(D\) 表示判別器,則 \(D(x_1)\) 表示判別樣本為正確的概率, \(1-D(x_1)\) 則對應着判別為錯誤樣本的概率。則有如下式子(這裏僅僅是對當前情況下的交叉熵損失的具體化)。

\[H((x_i, y_i)_{i=1}^N, D) = – \sum_{i=1}^N y_i\log D(x_i) – \sum_{i=1}^N(1-y_i)\log (1 – D(x_i)) \]

對於GAN中的樣本點 \(x_i\) ,對應於兩個出處,要麼來自於真實樣本,要麼來自於生成器生成的樣本 $\tilde{x} – G(z) $ ( 這裏的 \(z\) 是服從於投到生成器中噪聲的分佈)。

對於來自於真實的樣本,我們要判別為正確的分佈 \(y_i\) 。來自於生成的樣本我們要判別其為錯誤分佈( \(1-y_i\) )。將上面式子進一步使用概率分佈的期望形式寫出(為了表達無限的樣本情況,相當於無限樣本求和情況),並且讓 \(y_i\) 為 1/2 且使用 \(G(z)\) 表示生成樣本可以得到如下公式:

\[H \left( (x_i, y_i)_{i=1}^\infty, D \right) = -\frac{1}{2}E_{x-p_{data}}\left[ \log D(x) \right] – \frac{1}{2}E_z\left[ \log (1-D(G(z))) \right] \\\ GAN損失函數期望形式 \]

對於論文中的公式

\[min_G max_D V(D, G) = E_{x-p_{data}(x)}\left[ \log D(x) \right] + E_{z-p_z(z)}\left[ \log (1-D(G(z))) \right] \\\ GAN損失函數的 min max表達 \]

其實是與上面公式一樣的,下面做解釋

  • 這裏的 \(V(D, G)\) 相當於表示真實樣本和生成樣本的差異程度。
  • \(max_D V(D, G)\) 的意思是固定生成器 \(G\), 盡可能地讓判別器能夠最大化地判別出樣本來自於真實數據還是生成的數據。
  • 再將後面的 $L = max_D V(D, G) $ 看成整體,對於 \(min_G L\)這裡是在固定判別器\(D\)的條件下得到生成器 \(G\),這個 \(G\) 要求能夠最小化真實樣本與生成樣本的差異。
  • 通過上述 \(min\) \(max\) 的博弈過程,理想情況下會收斂於生成分佈擬合於真實分佈。

3、卷積對抗生成網絡

卷積對抗生成網絡(DCGAN)是在GAN的基礎上加入了CNN,主要是改進了網絡結構,在訓練過程中狀態穩定,並且可以有效實現高質量圖片的生成以及相關的生成模型應用。DCGAN的生成器網絡結構如下圖:

DCGAN的改進:

  • 使用步長卷積代替上採樣層,卷積在提取圖像特徵上具有很好的作用,並且使用卷積代替全連接層
  • 生成器G和判別器D中幾乎每一層都使用batchnorm層,將特徵層的輸出歸一化到一起,加速了訓練,提升了訓練的穩定性。
  • 在判別器中使用leakrelu激活函數,而不是RELU,防止梯度稀疏,生成器中仍然採用relu,但是輸出層採用tanh。

4、DCGAN代碼實現

shenduimport numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import optimizers, losses, layers, Sequential, Model
class DCGAN():
    '''
    實現深度對抗神經網絡
    生成 MNIST 手寫数字圖片
    輸入的噪聲為服從正態分佈均值為 0 方差為 1 的分佈, shape:(None, 100)
    生成器(G)輸入 噪聲, 輸出為 (None, 28, 28, 1)的圖片
    分類器(D)輸入為 (None, 28, 28, 1)的圖片,輸出圖片的分類真假
    '''
    def __init__(self):
        self.img_rows = 28 
        self.img_cols = 28
        self.channels = 1
        self.img_shape = (self.img_rows, self.img_cols, self.channels)

        optimizer = optimizers.Adam(0.0002)

        # 構建編譯分類器
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy', 
            optimizer=optimizer,
            metrics=['accuracy'])

        # 構建編譯生成器
        self.generator = self.build_generator()
        self.generator.compile(loss='binary_crossentropy', optimizer=optimizer)

        # 生成器輸入為噪音,生成圖片
        z = layers.Input(shape=(100,))
        img = self.generator(z)

        # 對於整個對抗網絡模型只優化生成器的參數
        self.discriminator.trainable = False

        # 用生成的圖片輸入分類器判斷
        valid = self.discriminator(img)

        # 對於整個對抗網絡 輸入噪音 => 生成圖片 => 決定圖片是否有效
        self.combined = Model(z, valid)
        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)

        
    def build_generator(self):
        '''
        構建生成器
        '''
        noise_shape = (100,)
        
        model = tf.keras.Sequential()
        
        # 添加全連接層
        model.add(layers.Dense(7*7*256, use_bias=False, input_shape=noise_shape))
        # 添加 BatchNormalization 層,對數據進行歸一化
        model.add(layers.BatchNormalization())
        model.add(layers.LeakyReLU())

        model.add(layers.Reshape((7, 7, 256)))
        
        # 添加逆卷積層,卷積核大小為 5X5,數量 128, 步長為 1
        model.add(layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False))
        assert model.output_shape == (None, 7, 7, 128)
        model.add(layers.BatchNormalization())
        model.add(layers.LeakyReLU())
        
        # 添加逆卷積層,卷積核大小為 5X5,數量 64, 步長為 2
        model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False))
        assert model.output_shape == (None, 14, 14, 64)
        model.add(layers.BatchNormalization())
        model.add(layers.LeakyReLU())
        
        # 添加逆卷積層,卷積核大小為 5X5,數量 1, 步長為 2
        model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh'))
        assert model.output_shape == (None, 28, 28, 1)
        
        model.summary()
        noise = layers.Input(shape=noise_shape)
        img = model(noise)
        
        # 返回 Model 對象,輸入為 噪聲, 輸出為 圖像
        return keras.Model(noise, img)

    
    def build_discriminator(self):
        '''
        構建分類器
        '''
        img_shape = (self.img_rows, self.img_cols, self.channels)
        
        model = tf.keras.Sequential()
        
        model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same',
                                         input_shape=img_shape))
        model.add(layers.LeakyReLU())
        # 添加 Dropout 層,減少參數數量
        model.add(layers.Dropout(0.3))

        model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
        model.add(layers.LeakyReLU())
        model.add(layers.Dropout(0.3))
        # 把數據鋪平
        model.add(layers.Flatten())
        model.add(layers.Dense(1))
        
        model.summary()
        
        img = layers.Input(shape=img_shape)
        validity = model(img)
        
        return keras.Model(img, validity)

    
    def train(self, epochs, batch_size=128, save_interval=50):
        '''
        網絡訓練
        '''
        # 加載 數據集
        (X_train, _), (_, _) = keras.datasets.mnist.load_data()

        # 把數據縮放到 [-1, 1]
        X_train = (X_train.astype(np.float32) - 127.5) / 127.5
        # 添加通道維度
        X_train = np.expand_dims(X_train, axis=3)
        half_batch = int(batch_size / 2)

        for epoch in range(epochs):

            # ---------------------
            #  訓練分類器
            # ---------------------

            # 隨機的選擇一半的 batch 數量圖片
            idx = np.random.randint(0, X_train.shape[0], half_batch)
            imgs = X_train[idx]

            noise = np.random.normal(0, 1, (half_batch, 100))

            # 生成一半 batch 數量的 圖片
            gen_imgs = self.generator.predict(noise)

            # 分類器損失
            d_loss_real = self.discriminator.train_on_batch(imgs, np.ones((half_batch, 1)))
            d_loss_fake = self.discriminator.train_on_batch(gen_imgs, np.zeros((half_batch, 1)))
            d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)


            # ---------------------
            #  訓練生成器
            # ---------------------

            noise = np.random.normal(0, 1, (batch_size, 100))

            # The generator wants the discriminator to label the generated samples
            # as valid (ones)
            # 對於生成器,希望分類器把更多的圖片判為 有效 (用 1 表示)
            valid_y = np.array([1] * batch_size)

            # 訓練生成器
            g_loss = self.combined.train_on_batch(noise, valid_y)

            # 打印訓練進度
            print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))

            # 每個 save_interval 周期保存一張圖片
            if epoch % save_interval == 0:
                self.save_imgs(epoch)

    def save_imgs(self, epoch):
        r, c = 5, 5
        noise = np.random.normal(0, 1, (r * c, 100))
        gen_imgs = self.generator.predict(noise)

        # 把圖片數據縮放到 0 - 1
        gen_imgs = 0.5 * gen_imgs + 0.5

        fig, axs = plt.subplots(r, c)
        cnt = 0
        for i in range(r):
            for j in range(c):
                axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')
                axs[i,j].axis('off')
                cnt += 1
        fig.savefig("dcgan/images/mnist_%d.png" % epoch)
        plt.close()

if __name__ == '__main__':
    dcgan = DCGAN()
    dcgan.train(epochs=10000, batch_size=32, save_interval=200)

網絡參數信息

5、訓練結果

下面是循環了 10000 次 epoch 后,從開始每隔 2000 個 epoch 生成器生成的圖片

  • 可以看到,剛開始全部都是噪聲,隨着訓練的進行,圖片逐漸清晰

  • 生成的圖片還是不太清晰,一方面的原因是我訓練的 epoch 周期太少,因為自己電腦性能問題,太耗時間,所以訓練的epoch 周期少,如果有條件后提高訓練周期應該會好很多。另一方面或許因為我構建的網絡還有不合理之,後期還需要改進。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

網頁設計最專業,超強功能平台可客製化