zoukankan      html  css  js  c++  java
  • 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.写两个线程,一个线程打印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方法用同步关键字修饰

  • 相关阅读:
    安装sublime text2 for ubuntu
    ruby中Regexp用法
    rvm is not a function的解决方法
    解决启动mongod 时,出现addr already in use错误
    rails中常用的插件
    在数据库中存储层次数据
    Formtastic: Forms Made Crazy Easy for Rails Developers
    rails安全性
    Rails 增加一个模型(model)
    RPC框架实现思路浅析
  • 原文地址:https://www.cnblogs.com/stars-one/p/10698277.html
Copyright © 2011-2022 走看看