• 06 多线程 01多线程概述 + 堆和方法区共享内存 + 分析程序存在几个线程 + 实现线程的两种方式 + 获取当前线程对象


    1、多线程概述

      /*
      * 1、什么是进程?什么是线程?
      *     进程是一个应用程序(1个进程是一个软件)
      *     线程是一个进程中的执行场景(执行单元)
      *     一个进程可以启动多个线程
      * 2、对于java程序来说,从dos窗口中输入:
      *     java helloWord 回车之后
      *     会先启动JVM,,而JVM就是一个进程
      *     同时再启动一个主线程调用main方法
      *     同时再启动一个垃圾回收线程负责看护,回收垃圾
      *     最起码,现在的java程序中至少有两个线程并发
      *     一个是垃圾回收线程,一个是执行main方法的主线程
      * 3、进程和线程是什么关系?
      *     阿里巴巴:进程
      *         童文红:阿里巴巴的一个线程
      *         马云:阿里巴巴的一个线程
      *     京东:进程
      *         强东:京东的一个线程
      *         奶茶:京东的一个线程
      *     进程可以看做现实生活中的公司
      *     线程可以看做公司的某个员工
      *     注意:
      *         进程A和进程B内存独立不共享资源
      *         线程A和线程B呢?
      *             线程A和线程B,堆内存和方法区内存共享
      *             当时栈内独立,一个线程一个栈
      *             假设启动10个线程,会有10个栈,每个栈和每个栈之间,互不干扰,各自执行各自的,这就是多线程并发
      *         火车站:进程
      *         火车站窗口:一个售票窗口是一个线程   再每个售票窗口,你不等我,我不等你,提高效率
      *     4、思考一个问题?
      *         使用了多线程机制,main方法结束,是不是有可能程序结束
      *         main方法结束,只是主线程结束了,其他的栈(线程)可能还在压栈弹栈
      * */

    2、堆和方法区共享内存

     /*
            * 1、分析一个问题,对于单核的CPU来说,真的可以做到真正的多线程并发吗?
            * 对于多核的CPU电脑来说,真正的多线程并发没有问题。4核CPU表示同一个时间点上,可以真正的4个进程并发执行
            *   什么是真正的多线程并发?
            *   t1线程执行t1的
            *   t2线程执行t2的
            *   t1不会影响t2,t2也不会影响t1,这叫真正的多线程并发
            *   单核的CPU只有一个大脑:
            *       能够做到真正的多线程并发,但是可以做到给人一种“多线程并发”的感觉
            *       对于单核的CPU来说,在某个时间点上实际上只能处理一件事情,但是由于CPU的执行速度极快,多个线程之间频繁切换执行,跟人来的感觉就是,
            *       多个事情同时在做         
            *       线程A:播放音乐
            *       线程B:运行魔兽游戏
            *       线程A和线程B频繁切换,给人的感觉就是一会儿播放音乐,一会儿运行游戏
            *   电影院采用胶卷播放电影,一个胶卷一个胶卷播放速度达到一定程度之后
            *   人类的眼睛产生了错觉,感觉是动画的,这说明人类的反应速度很慢,就像一根钢针扎到手上,到最终感觉到疼,这个过程是需要“很长的”时间,在这个期间计算机可以
            *   进行亿万次的循环,所以计算机的执行速度很快
            * */

    3、分析程序存在几个线程

    /*
    * 大家分析有几个线程?
    *   1、一个线程,垃圾回收器
    *   2、只有一个主线程,没有启动分支栈,没有启动分支栈,一个栈中,自上而下的顺序执行
    * */
    
    public class HashSet01 {
    
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            System.out.println("main begin");
            m1();
            System.out.println("main over");
        }
        private static void m1(){
            System.out.println("m1 begin");
            m2();
            System.out.println("m2 over");
        }
        private static void m2(){
            System.out.println("m2 begin");
            m3();
            System.out.println("m2 over");
        }
         private static void m3(){
             System.out.println("m3 execute");
         }

     4、实现线程的两种方式

    /*
    * 实现线程的第一种方式:
    *   编写一个类,直接继承java.lang.Thread  重写run方法
    *   怎么创建线程对象?new就可以了
    *   怎么启动线程呢?调用线程对象的start方法
    * 注意:亘古不变的道理:方法体中的代码永远都是自上而下的顺序依次逐行执行
    * 以下程序的输出结果有这样的特点:
    *   有先有后
    *   有多有少
    * 第一种方式:
    *   定义线程类
    *   public class MyTread extends Thread{
    *   public void run(){
    *
    *   }
    *   //创建线程对象
    *   MyThread my = new MyThread();
    *   //启动线程
    *   my.start();
    * 第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法
    *   //定义一个可运行的类
    *   public  class MyRunnable implements Runnable {
    *   public  void run(){
    * }
    * }
    * //创建线程对象
    * Thread t = new Thread(new MyRunnable());
    * //启动线程
    * t.start()
    * }
    * 注意:第二种方式实现接口比较常用,因为一个类实现了接口,它还可以继承其他的类,更灵活
    *
    *
    *
    *
    *
    * */
    public class ThreadTest {
        public static void main(String[] args) {
            //这里是main方法,这里的代码属于主线程,在主栈中运行
            //新建一个分支线程对象
            MyThread myThread = new MyThread();
           // myThread.run();  //不会启动线程,不会分配新的分支栈(这种方式是分支线程)
            //启动线程
            //start()方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束了
            //这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开辟出来,start()方法就结束了,线程就启动成功了
            //启动成功的线程会自动调用run方法,并且run方法在分支栈的栈底部(压栈)
            //run方法在分支栈的底部,main方法在主栈的栈底部,run和main是平级的
            myThread.start();   //开辟分支栈
    
            //这里的代码还是运行在主线程中
            for(int i = 0; i < 1000; i++){
                System.out.println("主线程----》" + i);
            }
    
            //创建线程对象,采用匿名内部类方式
            //这是通过一个没有名字的类,new出来的对象
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int i = 0; i < 100; i++){
                        System.out.println("分支线程》》》》》》》》" + i);
                    }
                }
            });
            //启动线程
            t.start();
            for(int i  = 0; i < 100; i++){
                System.out.println("主线程》》》》》》》》》》》" + i);
            }
    
    
        }
    }
    
    class MyThread extends Thread{
        public void run(){
            //编写程序,这段程序运行在分支线程中(分支栈)
            for(int i = 0; i < 1000; i++){
                System.out.println("分支线程-----》" + i);
            }
        }
    }
    /**
     * Created by Mike
     */
    public class ThreadTest01 {
    
        /*
        *
        * 实现java.lang.Runnable接口
        * */
    
    
        public static void main(String[] args) {
            //创建一个可运行的对象
            MyRunnnable r = new MyRunnnable();
            //将可运行的对象封装为一个线程对象
            Thread t = new Thread(r);
            //启动线程
            t.start();
    
            //主线程
            for(int i = 0; i < 1000; i++){
                System.out.println("主线程》》》》》》》》》》" + i);
            }
    
        }
    }
    
    // 这并不是一个线程,而是一个可运行的类,它还不是一个线程
    class MyRunnnable implements  Runnable{
    
    
        @Override
        public void run() {
            for(int i = 0; i < 1000; i++){
                System.out.println("分支线程》》》》》》》》》》" + i);
            }
        }
    }

    5、获取当前线程对象

     /*
        *
        * 1、怎么获取当前线程对象?
        *   static Thread currentThread()
        * 2、获取线程对象的名字
        *   String name = 线程对象.getName()
        * 3、修改线程对象的名字
        *   "线程对象".setName(newName)
        * 4、当线程没有设置名字的时候,默认名字有什么规律
        *   Thread-0
        *   Thread-1
        * */
     //创建线程对象
            MyThread t = new MyThread();
            //设置线程名字
            t.setName("tttt");
            //获取线程名字
            String tName = t.getName();
            System.out.println(tName);   //Thread 0
    
            //启动线程
            t.start();
            System.out.println();
           for(int i = 0; i < 1000; i++){
                //currentThread 就是当前线程对象,出现在哪就是当前线程对象
                Thread currentThread = Thread.currentThread();
                System.out.println("分支线程》》》》》》》》》》" + i);
            }

    6、终断线程的睡眠

     public static void main(String[] args) {
            /*
            * 关于线程的sleep方法
            *   static  void  sleep(long millis)
            *   1、静态方法:Thread.sleep(100);
            *   2、参数是毫秒
            *   3、作用:让当前线程进入休眠,进入“阻塞状态”,放弃占有CPU时间片,让给其他线程使用
            *           这行代码出现在A线程中,A线程就会进入休眠
            *           这行代码出现在B线程中,B线程就会进入休眠
            *   4、Thread.sleep()方法,可以做到这种效果,间隔特定的时间,去执行一段特定的代码,每隔多久执行一次
            *   5、sleep睡眠太久了,如果希望半道上醒来,要终止线程的睡眠,而不是中断线程的执行 "线程对象".interrupt()
            *
            *
            * */
            //让当前线程进入休眠,睡眠5秒
            //当前线程是主线程
            Thread t = new Thread(new MyRunnnable());
            t.start();
            t.interrupt();
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    // 这并不是一个线程,而是一个可运行的类,它还不是一个线程
    class MyRunnnable implements  Runnable{
    
        //重点:run()当中的异常不能throws,只能try   catch
        //因为run()方法在父类中没有抛出任何异常,子类不能比父类抛出更多的异常
    
    
        @Override
        public void run() {
            System.out.println("分支线程》》》》》》》》》》");
            try {
                Thread.sleep(1000 * 60 * 60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //终断t线程的睡眠(这种终断睡眠的方式,依靠了java的异常处理机制
            Thread.interrupted();
            System.out.println("线程终断");
        }
    }
  • 相关阅读:
    npm安装elasticsearch-reindex
    Linux14_文本编辑器与终端配置
    Linux13_群组的管理和文件权限的管理
    Linux12_用户和权限
    Linux11_文件及目录以及其相关的组织命令
    Linux10_常用命令和操作
    Linux9_安装Linux系统
    基础概念——什么是POSIX
    C++Review21_宏和常量
    C++Review20_C++函数高级特性(重载、内联、const和virtual)
  • 原文地址:https://www.cnblogs.com/xiaoming521/p/15846969.html
Copyright © 2020-2023  润新知