zoukankan      html  css  js  c++  java
  • Java自学-多线程 常见线程方法

    Java 常见的线程方法

    示例 1 : 当前线程暂停

    Thread.sleep(1000); 表示当前线程暂停1000毫秒 ,其他线程不受影响
    Thread.sleep(1000); 会抛出InterruptedException 中断异常,因为当前线程sleep的时候,有可能被停止,这时就会抛出 InterruptedException

    package multiplethread;
     
    public class TestThread {
     
        public static void main(String[] args) {
             
            Thread t1= new Thread(){
                public void run(){
                    int seconds =0;
                    while(true){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.printf("已经玩了LOL %d 秒%n", seconds++);
                    }              
                }
            };
            t1.start();
             
        }
         
    }
    

    示例 2 : 加入到当前线程中

    首先解释一下主线程的概念
    所有进程,至少会有一个线程即主线程,即main方法开始执行,就会有一个看不见的主线程存在。
    在42行执行t.join,即表明在主线程中加入该线程
    主线程会等待该线程结束完毕, 才会往下运行。

    package multiplethread;
      
    import charactor.Hero;
      
    public class TestThread {
      
        public static void main(String[] args) {
              
            final Hero gareen = new Hero();
            gareen.name = "盖伦";
            gareen.hp = 616;
            gareen.damage = 50;
      
            final Hero teemo = new Hero();
            teemo.name = "提莫";
            teemo.hp = 300;
            teemo.damage = 30;
              
            final Hero bh = new Hero();
            bh.name = "赏金猎人";
            bh.hp = 500;
            bh.damage = 65;
              
            final Hero leesin = new Hero();
            leesin.name = "盲僧";
            leesin.hp = 455;
            leesin.damage = 80;
              
            Thread t1= new Thread(){
                public void run(){
                    while(!teemo.isDead()){
                        gareen.attackHero(teemo);
                    }              
                }
            };
              
            t1.start();
     
            //代码执行到这里,一直是main线程在运行
            try {
                //t1线程加入到main线程中来,只有t1线程运行结束,才会继续往下走
                t1.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
     
            Thread t2= new Thread(){
                public void run(){
                    while(!leesin.isDead()){
                        bh.attackHero(leesin);
                    }              
                }
            };
            //会观察到盖伦把提莫杀掉后,才运行t2线程
            t2.start();
              
        }
          
    }
    

    示例 3 : 线程优先级

    当线程处于竞争关系的时候,优先级高的线程会有更大的几率获得CPU资源
    为了演示该效果,要把暂停时间去掉,多条线程各自会尽力去占有CPU资源
    同时把英雄的血量增加100倍,攻击减低到1,才有足够的时间观察到优先级的演示
    如图可见,线程1的优先级是MAX_PRIORITY,所以它争取到了更多的CPU资源执行代码

    线程优先级

      package charactor;
          
        import java.io.Serializable;
           
        public class Hero{
            public String name;
            public float hp;
              
            public int damage;
              
            public void attackHero(Hero h) {
                //把暂停时间去掉,多条线程各自会尽力去占有CPU资源
                //线程的优先级效果才可以看得出来
        //        try {
        //           
        //            Thread.sleep(0);
        //        } catch (InterruptedException e) {
        //            // TODO Auto-generated catch block
        //            e.printStackTrace();
        //        }
                h.hp-=damage;
                System.out.format("%s 正在攻击 %s, %s的血变成了 %.0f%n",name,h.name,h.name,h.hp);
                  
                if(h.isDead())
                    System.out.println(h.name +"死了!");
            }
          
            public boolean isDead() {
                return 0>=hp?true:false;
            }
          
        }
    
    
    package multiplethread;
      
    import charactor.Hero;
      
    public class TestThread {
      
        public static void main(String[] args) {
              
            final Hero gareen = new Hero();
            gareen.name = "盖伦";
            gareen.hp = 6160;
            gareen.damage = 1;
      
            final Hero teemo = new Hero();
            teemo.name = "提莫";
            teemo.hp = 3000;
            teemo.damage = 1;
              
            final Hero bh = new Hero();
            bh.name = "赏金猎人";
            bh.hp = 5000;
            bh.damage = 1;
              
            final Hero leesin = new Hero();
            leesin.name = "盲僧";
            leesin.hp = 4505;
            leesin.damage = 1;
              
            Thread t1= new Thread(){
                public void run(){
     
                    while(!teemo.isDead()){
                        gareen.attackHero(teemo);
                    }              
                }
            };
              
            Thread t2= new Thread(){
                public void run(){
                    while(!leesin.isDead()){
                        bh.attackHero(leesin);
                    }              
                }
            };
             
            t1.setPriority(Thread.MAX_PRIORITY);
            t2.setPriority(Thread.MIN_PRIORITY);
            t1.start();
            t2.start();
              
        }
          
    }
    

    示例 4 : 临时暂停

    当前线程,临时暂停,使得其他线程可以有更多的机会占用CPU资源

    package multiplethread;
      
    import charactor.Hero;
      
    public class TestThread {
      
        public static void main(String[] args) {
              
            final Hero gareen = new Hero();
            gareen.name = "盖伦";
            gareen.hp = 61600;
            gareen.damage = 1;
      
            final Hero teemo = new Hero();
            teemo.name = "提莫";
            teemo.hp = 30000;
            teemo.damage = 1;
              
            final Hero bh = new Hero();
            bh.name = "赏金猎人";
            bh.hp = 50000;
            bh.damage = 1;
              
            final Hero leesin = new Hero();
            leesin.name = "盲僧";
            leesin.hp = 45050;
            leesin.damage = 1;
              
            Thread t1= new Thread(){
                public void run(){
     
                    while(!teemo.isDead()){
                        gareen.attackHero(teemo);
                    }              
                }
            };
              
            Thread t2= new Thread(){
                public void run(){
                    while(!leesin.isDead()){
                        //临时暂停,使得t1可以占用CPU资源
                        Thread.yield();
                         
                        bh.attackHero(leesin);
                    }              
                }
            };
             
            t1.setPriority(5);
            t2.setPriority(5);
            t1.start();
            t2.start();
              
        }
          
    }
    

    示例 5 : 守护线程

    守护线程的概念是: 当一个进程里,所有的线程都是守护线程的时候,结束当前进程。

    就好像一个公司有销售部,生产部这些和业务挂钩的部门。
    除此之外,还有后勤,行政等这些支持部门。

    如果一家公司销售部,生产部都解散了,那么只剩下后勤和行政,那么这家公司也可以解散了。

    守护线程就相当于那些支持部门,如果一个进程只剩下守护线程,那么进程就会自动结束。

    守护线程通常会被用来做日志,性能统计等工作。

    package multiplethread;
      
    public class TestThread {
      
        public static void main(String[] args) {
              
            Thread t1= new Thread(){
                public void run(){
                    int seconds = 0;
                     
                    while(true){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.printf("已经玩了LOL %d 秒%n", seconds++);
                         
                    }              
                }
            };
            t1.setDaemon(true);
            t1.start();
              
        }
          
    }
    

    练习破解密码

    1. 生成一个长度是3的随机字符串,把这个字符串当作 密码

    2. 创建一个破解线程,使用穷举法,匹配这个密码

    3. 创建一个日志线程,打印都用过哪些字符串去匹配,这个日志线程设计为守护线程

    提示: 破解线程把穷举法生成的可能密码放在一个容器中,日志线程不断的从这个容器中拿出可能密码,并打印出来。 如果发现容器是空的,就休息1秒,如果发现不是空的,就不停的取出,并打印。

    答案

    穷举密码的线程

    package multiplethread;
     
    import java.util.List;
     
    public class PasswordThread extends Thread{
     
        private boolean found = false;
         
        private String password;
     
        private List<String> passwords;
     
        public PasswordThread(String password, List<String> passwords) {
            this.password = password;
            this.passwords = passwords;
        }
         
        public void run(){
            char[] guessPassword = new char[password.length()];
            generatePassword(guessPassword, password);
        }
     
        public  void generatePassword(char[] guessPassword, String password) {
            generatePassword(guessPassword, 0, password);
        }
     
        public  void generatePassword(char[] guessPassword, int index, String password) {
            if (found)
                return;
            for (short i = '0'; i <= 'z'; i++) {
                char c = (char) i;
                if (!Character.isLetterOrDigit(c))
                    continue;
                guessPassword[index] = c;
                if (index != guessPassword.length - 1) {
                    generatePassword(guessPassword, index + 1, password);
                } else {
                    String guess = new String(guessPassword);
                    //穷举每次生成的密码,都放进集合中
                    passwords.add(guess);
                    if (guess.equals(password)) {
                        System.out.println("找到了,密码是" + guess);
                        found = true;
                        return;
                    }
                     
                }
            }
        }
         
    }
    

    记录日志的守护线程

    package multiplethread;
     
    import java.util.List;
     
    public class LogThread extends Thread{
        private boolean found = false;
     
        private List<String> passwords;
     
        public LogThread(List<String> passwords) {
            this.passwords = passwords;
             
            this.setDaemon(true);//把记日志的这个线程,设置为守护线程
        }
         
        public void run(){
            while(true){
                while(passwords.isEmpty()){
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                 
                String password = passwords.remove(0);
                System.out.println("穷举法本次生成的密码是:" +password);
            }
        }
         
    }
    

    测试类

    package multiplethread;
     
    import java.util.ArrayList;
    import java.util.List;
     
    public class TestThread {
     
        public static boolean found = false;
         
        public static void main(String[] args) {
            String password = randomString(3);
            System.out.println("密码是:" + password);
            List<String> passwords = new ArrayList<>();
             
            new PasswordThread(password,passwords).start();
            new LogThread(passwords).start();
             
        }
     
        private static String randomString(int length) {
            String pool = "";
            for (short i = '0'; i <= '9'; i++) {
                pool += (char) i;
            }
            for (short i = 'a'; i <= 'z'; i++) {
                pool += (char) i;
            }
            for (short i = 'A'; i <= 'Z'; i++) {
                pool += (char) i;
            }
            char cs[] = new char[length];
            for (int i = 0; i < cs.length; i++) {
                int index = (int) (Math.random() * pool.length());
                cs[i] = pool.charAt(index);
            }
            String result = new String(cs);
            return result;
        }
     
    }
    
  • 相关阅读:
    SQLServer提取日期中的年月日及其他格式
    大白话解说,半分钟就懂 --- 分布式与集群是什么 ? 区别是什么?
    VS2015 Git 源码管理工具简单入门
    Web.Config配置文件中customErrors元素的使用方法
    C#发起Http请求,调用接口
    如何停止和禁用Linux系统中的不需要的服务
    QtCreator调试传入运行参数
    gSOAP 在windows下的安装与使用(mingw32)
    MinGW 使用 mintty 终端替代默认终端以解决界面上复制与粘贴的问题
    在windows下执行./configure,make,makeinstall源码安装程序spice-gtk
  • 原文地址:https://www.cnblogs.com/jeddzd/p/12368086.html
Copyright © 2011-2022 走看看