zoukankan      html  css  js  c++  java
  • java高并发-认识线程

    1.一般的代码

    import java.util.concurrent.TimeUnit;
    
    public class TryConcurrency {
        private static void browseNews() {
            for ( ; ;) {
                System.out.println("uh-huh, the good news.");
                sleep(1);
            }
        }
    
        private static void enjoyMusic() {
            for ( ; ; ) {
                System.out.println("uh-huh, the nice music.");
                sleep(1);
            }
        }
    
        private static void sleep(int seconds) {
            try {
                TimeUnit.SECONDS.sleep(seconds);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args) {
            browseNews();
            enjoyMusic();
        }
    } 

    遗憾的是上面一直打印 uh-huh, the good news.

    所以我们要引入Thread,重写其中的main方法

    public static void main(String[] args) {
      new Thread() {
        public void run() {
          browseNews();
        }
      }.start();
       enjoyMusic();
    }
    

    start()方法是一个立即返回的方法,并不会让程序陷入阻塞

    引入Lambda表达式

    public static void main(String[] args) {
      new Thread(TryConcurrency::browseNews).start();
       enjoyMusic();
    }
    

    会使代码更清晰

    2.线程的生命周期

    new(新建状态)

    使用new创建了一个Thread对象时,并不处于执行状态,当.start()之后,就会进入runnable状态

    runnable(可执行状态)

    当调用run()方法之后,线程就进入了runnable状态,并且在jvm线程中创建了一个线程,但是此时线程仍然没有运行,它需要听从cpu的调度,称之为可执行状态

    running(执行中状态)

    当cpu在众多线程的可执行队列中选中了该线程,那么就会真正的执行自己的逻辑代码,该状态称之为运行状态

    当线程调用stop()方法或者判断某个业务逻辑标识时,就会进入terminated状态

    当线程调用sleep或者wait方法,就会进入blocked状态

    当线程进行某个阻塞的io操作时,就会进入blocked状态

    当获取某个资源文件而加入到阻塞队列中,就会进入blocked状态

    当cpu的调度器轮询使该线程放弃执行,就会进入runnable状态

    当线程调用yield方法,放弃cpu执行权,就会进入runnable状态

    blocked(阻塞状态)

    调用stop方法,或者意外死亡,就会进入terminated状态

    线程阻塞结束,就会进入runnable状态

    线程完成了指定休眠,就会进入runnable状态

    等待状态(wait)线程被其他线程notify/notifyall唤醒,就会进入runnable状态

    线程获取到某个锁的资源,进入runnable状态

    线程在阻塞状态过程中被打断,比如其他线程调用了interrupt方法,线程就会进入runnable状态

    terminated(死亡状态)

    程序正常结束,线程意外死亡,jvm crash,线程进入terminated

    3.我们在调用start方法时,为什么会执行run方法

    是因为run方法被jni方法的start0调用,事实上threadStatus的内部属性是0;

    不能两次启动Thread,否则会出现非法线程状态异常

    线程启动后会被加入到ThreadGroup中

    当线程进入死亡状态的时候,是不允许调用start方法,也就是说死亡状态下的线程是不允许回到可执行状态/执行状态

    4.Thread的run和start就是一个典型的模板设计模式,父类编写算法结构代码,子类实现逻辑细节

    5.Thread模拟营业大厅叫号机程序

    public class TicketWindow extends Thread {
    
        private final String name;
    
        private static final int MAX = 50;
    
        private static int index = 1;
    
        public TicketWindow(String name) {
            this.name = name;
        }
    
        @Override
        public void run() {
            while (index < MAX) {
                System.out.println("柜台:" + name + " 当前的号码是:" + (index++));
            }
        }
    
        public static void main(String[] args) {
            TicketWindow ticketWindow1 = new TicketWindow("一号机橱柜");
            ticketWindow1.start();
            TicketWindow ticketWindow2 = new TicketWindow("二号机橱柜");
            ticketWindow2.start();
            TicketWindow ticketWindow3 = new TicketWindow("三号机橱柜");
            ticketWindow3.start();
            TicketWindow ticketWindow4 = new TicketWindow("四号机橱柜");
            ticketWindow4.start();
        }
    }
    

    拓展:

    static关键字:

    (1)修饰变量,方法,内部类,代码块

    (2)static修饰的内容优于对象,随着类创建的同时一起创建

    (3)static修饰的内容存在于方法区的静态区,成员变量存在于堆内存的对象中

    6.Thread和Runnable的关系

    Thread是获取数据,Runnable是逻辑处理

    Thread类的run方法是不能共享的,Runnable接口中的run方法很容易实现共享

    public class TicketWindowRunnable implements Runnable{
    
        private Integer index = 1;
    
        private final static Integer MAX = 50;
    
        @Override
        public void run() {
            while (index <= MAX) {
                System.out.println(Thread.currentThread() + " 的号码是:" + (index++));
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public class Bank2 {
    
        public static void main(String[] args) {
            final TicketWindowRunnable ticketWindowRunnable = new TicketWindowRunnable();
            Thread thread1 = new Thread(ticketWindowRunnable, "一号窗口");
            Thread thread2 = new Thread(ticketWindowRunnable, "二号窗口");
            Thread thread3 = new Thread(ticketWindowRunnable, "三号窗口");
            Thread thread4 = new Thread(ticketWindowRunnable, "四号窗口");
            thread1.start();
            thread2.start();
            thread3.start();
            thread4.start();
        }
    }
    

    但是仍然会有两个同样的号码,或者有的号码没有出现,这就涉及线程安全的问题

  • 相关阅读:
    pycharm中出现unresolved reference的解决办法
    MVC4中基于bootstrap和HTML5的图片上传Jquery自定义控件
    Demo中的IOC自定义实现
    MVC 导出Excel 的其中一方法(View导出excel)
    MVC 定时执行任务
    Bootstrap.css 中请求googleapis.com/css?family 备忘录
    JqueryUI Dialog 加载动态页 部分页
    Android中EditText的常见属性
    安卓程序崩溃异常处理
    获取鼠标句柄
  • 原文地址:https://www.cnblogs.com/freeht/p/12891268.html
Copyright © 2011-2022 走看看