1. 程式人生 > >Java 學習筆記 線程控制

Java 學習筆記 線程控制

不知道 package start return 關鍵字 bug creat 沒有 stat

題目一

本質上來說,線程是不可控制的,線程的執行是由CPU資源分配決定的,我們無法幹預系統CPU的資源分配,但我們可以增加條件來讓線程按照我們的預想順序來執行。
比如。如果當前的執行的線程不滿足我們所定的條件,那麽就讓CPU重新進行資源的分配,直到資源分配給我們所需要的某個線程

題目說明

編寫一個線程類(只有一個類),創建三個線程實例:A線程對象、B線程對象、C線程對象;A線程完成打印“A”, B線程完成打印“B”, C線程完成打印“C”;按照ABC,ABC,ABC……這樣來輸出。

思路

創建一個存放char的類,以線程名和char的數值為條件,從而控制指定的線程執行
如果單單只靠線程名,不能保證第一次運行的線程是A,線程調用start方法只是進入到就緒狀態,需要獲得CPU資源才能執行

代碼

MyChar.java

package HomeWork2;

/**
 * @author StarsOne
 * @date Create in  2019-4-9 0009 19:53:39
 * @description
 */
class MyChar {
    private char c = 'A';

    public MyChar() {

    }

    public char getC() {
        return c;
    }

    public void setC(char c) {
        this.c = c;
    }
}

PrintThread.java

package HomeWork2;

/**
 * @author StarsOne
 * @date Create in  2019-4-9 0009 19:53:27
 * @description
 */
class PrintThread extends Thread {
    private MyChar myChar ;

    public PrintThread(String name, MyChar myChar) {
        super(name);
        this.myChar = myChar;
        setDaemon(true);//設置為守護進程,主線程停止,當前的子線程也停止
    }

    @Override
    public void run() {
        while (true) {
            synchronized (myChar) {
                if (getName().charAt(0) == 'A' && myChar.getC() == 'A') {
                    System.out.print("A");
                    myChar.setC('B');//修改mychar裏面值,使得線程按指定順序執行
                }else if (getName().charAt(0) == 'B' && myChar.getC() == 'B'){
                    System.out.print("B");
                    myChar.setC('C');
                }else if (getName().charAt(0) == 'C' && myChar.getC() == 'C'){
                    System.out.print("C,");
                    myChar.setC('A');
                }
            }
            try {
                sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
    public static void main(String[] args) {
        MyChar myChar = new MyChar();
        //註意這裏,某個線程傳入的都是同一個對象mychar
        new PrintThread("A", myChar).start();
        new PrintThread("C", myChar).start();
        new PrintThread("B", myChar).start();

        //主線程休眠
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

題目二

題目說明

3.寫兩個線程,一個線程打印1~52,另一個線程打印A~Z,打印順序是12A34B...5152Z;

思路

  • 兩個線程,NumberPrintThreadCharPrintThread,前者打印數字,後者打印字符
  • 需要一個CharFlag類,其中有個flag標誌,標誌接下來要打印數字還是字符

CharFlag.java

package HomeWork3;

/**
 * @author StarsOne
 * @date Create in  2019-4-9 0009 20:37:49
 * @description
 */
class CharFlag {
    private boolean flag = false;//默認為false,因為先輸出數字

    public boolean isFlag() {
        return flag;
    }

    public synchronized void changeFlag() {
        this.flag = !flag;
    }
}

CharPrintThread.java

package HomeWork3;

/**
 * @author StarsOne
 * @date Create in  2019-4-9 0009 20:37:09
 * @description
 */
class CharPrintThread extends Thread {
    private CharFlag charFlag;

    public CharPrintThread(CharFlag charFlag) {
        this.charFlag = charFlag;
    }

    private char c = 'A';
    @Override
    public void run() {
        while (c <= 'Z') {
            if (charFlag.isFlag()) {
                System.out.print(c+" ");//為了好看,加了個空格
                charFlag.changeFlag();
                c++;//註意這個遞增的位置
            }

        }
        try {
            sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

NumberPrintThread.java

package HomeWork3;

/**
 * @author StarsOne
 * @date Create in  2019-4-9 0009 20:37:09
 * @description
 */
class NumberPrintThread extends Thread {
    private int num =1;
    private CharFlag charFlag;

    public NumberPrintThread(CharFlag charFlag) {
        this.charFlag = charFlag;
    }

    @Override
    public void run() {
        //num到52結束輸出
        while (num<=52) {
            if (!charFlag.isFlag()) {
                System.out.print(num);
                if (num % 2 == 0) {
                    charFlag.changeFlag();
                }
                num++;//註意這個遞增的位置
            }

        }
        try {
            sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Test.java

package HomeWork3;

/**
 * @author StarsOne
 * @date Create in  2019-4-9 0009 20:45:14
 * @description
 */
class Test {
    public static void main(String[] args) {
        final CharFlag charFlag = new CharFlag();
        new CharPrintThread(charFlag).start();
        new NumberPrintThread(charFlag).start();
    }
}

PS:不知道出現了什麽bug,多次運行後會輸出一部分之後就沒有輸出了,但是程序仍然在執行,似乎是死鎖問題?
上面的代碼中,出現了死鎖問題,因為sleep方法放在了while循環的外頭,兩個while循環,都會對flag就行修改,獲取的方法不是使用同步關鍵字修飾,所以就會造成死鎖問題
解決方法:
----
把sleep方法放在while循環中,或者把getFlag方法用同步關鍵字修飾

Java 學習筆記 線程控制