Java 学习笔记 线程控制

题目一

本质上来说,线程是不可控制的,线程的执行是由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.写两个线程,一个线程打印152,另一个线程打印AZ,打印顺序是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方法用同步关键字修饰

posted @ 2019-04-12 20:32  Stars-one  阅读(539)  评论(0编辑  收藏  举报