ACAC 线程概述(简单实现)

/**
 * 1、什么是进程?什么是线程?
 *    进程是一个应用程序(一个进程是一个软件)
 *    线程是一个进程中的执行场景/执行单元
 *    一个进程可以启动多个线程
 *
 * 2、对于java程序来说,当在Dos窗口输入:
 *      java HelloWorld回车之后,会先启动JVM,JVM就是一个线程
 *      JVM再启动一个主线程调用main方法,同时启动一个垃圾回收线程负责看护,回收垃圾
 *      最少java程序中至少有两个线程并发:一个是垃圾回收线程,一个是执行main方法的主线程
 *
 * 3、线程和进程是什么关系?现实
 *      阿里:进程
 *      马云:阿里的一个线程
 *      童文红:阿里的一个线程
 *
 *      王者大陆:进程
 *      英雄:王者大陆的一个线程
 *      野怪:王者大陆的一个线程
 *
 *      进程可以看做一个公司,线程是公司里的某个员工
 *
 *   注意:进程A和进程B的内存不会共享(公司之间不会共享资源)
 *
 *        线程A和线程B:
 *          java语言中,线程A和线程B,堆内存和方法区,内存共享
 *          栈内存独立,一个进程一个栈
 *        如果有10个线程启动,就会有10个栈空间,栈之间不会互相干扰,叫做多线程并发
 *
 *   java中之所以有多线程机制,目的就是为了提高程序的处理效率。
 *
 * 4、main方法结束了,程序就结束了吗?
 *   不一定,因为main方法结束了只是主线程结束了,主栈空了,其他的栈(线程)可能还在压栈弹栈。
 *
 * 5、对于单核CPU来说不能做到真正的多线程并发:
 *      但由于CPU的运算速度极快,多个线程之间频繁的切换,给人的感觉是多个事情同时做
 *      如:一边放音乐,一边运行游戏,
 *
 *    真正的多线程并发:是在某一个时间点上,可以同时处理多个线程的
 *
 * 6、java语言中,实现进程有两种方式:
 *      java支持多线程机制,并且java已经将多线程实现了,我们只需要继承就可以
 *   实现线程的第一种方式:
 *           编写一个类,直接继承java.lang.Thread 重写run方法
 *           //定义线程类
 *           public class MyThread extends Thread{
 *               public void run(){
 *
 *               }
 *           }
 *           //创建线程对象
 *           MyThread aa = new MyThread();
 *           //启动线程
 *           aa.start();
 *   第二种方式,编写一个类,实现java.lang.Runnable接口,实现run方法
 *          //定义一个可运行的类
 *          public class MyRunnable implements Runnable{
 *              public void run(){
 *
 *              }
 *          }
 *
 *          //创建线程对象
 *          Thread t = new Thread(new MyRunnable());
 *          //启动线程
 *          t.start();
 *
 *    注意:第二种方式实现接口比较常用,因为一个类实现了接口,还可以继承其他的类,更灵活。
 *
 */
public class Note {
}

/*
* 实现线程的第一种方式:
*   编写一个类,直接继承java.lang.Thread 重写run方法
* */
public class ThreadTest01 {
    
    
    public static void main(String[] args) {
    
    

        MyThread m = new MyThread();
        //m.run();这样写,没有调用多线程,只是调用了一个普通方法而已
        m.start();
        /**
         * start方法的作用:
         *     启动一个分支线程,在JVM中开辟出一个新的栈空间,开辟完成后,这段代码瞬间就结束了
         *          而里面的run方法,是有JVM自动调用的,不需要手动调用
         *     只要新的栈空间开出来,start()方法就结束了,线程就启动成功了
         *          启动成功的线程会自动调用run方法,并且run方法在分支栈的底部(压栈)
         *          和main方法一样(main方法是在主栈的底部),它俩是平级的
         *
         *  注意:代码仍然是自上而下依次执行的(java中亘古不变的定理)
         */
        for (int i = 0; i < 666; i++) {
    
    
            System.out.println("主线程--》" + i);
        }

    }

}
class MyThread extends Thread{
    
    

    @Override
    public void run() {
    
    
        //编写程序,这段程序运行在分支程序(分支栈)中
        for (int i = 0; i < 666; i++) {
    
    
            System.out.println("分支线程---》" + i);
        }
    }
}
/*
* 实现线程的第二种方式:编写一个类,实现java.lang.Runnable接口
* */
public class ThreadTest02 {
    
    
    public static void main(String[] args) {
    
    

        MyRunnable m = new MyRunnable();
        Thread r = new Thread(m);

        //直接合并也行
        Thread e = new Thread(new MyRunnable());

        //匿名内部类,其实也相当于class a implements Runnalbe,就是这个a,没有名字
        Thread f = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                for (int i = 0; i < 666; i++) {
    
    
                    System.out.println("匿名内部类--->" + i);

                }
            }
        });

        f.start();
        //e.start();
        r.start();
        for (int i = 0; i < 666; i++) {
    
    
            System.out.println("主线程-->" + i);
        }
    }
}
class MyRunnable implements Runnable{
    
    

    @Override
    public void run() {
    
    
        for (int i = 0; i < 666; i++) {
    
    
            System.out.println("分支线程--->" + i);
        }
    }
}
/**
 * 1、怎么获取当前线程对象?
 *  static Thread currentThread()
 *
 * 2、获取线程对象的名字
 *       my.getName();
 * 3、修改线程对象的名字
 *       my.setName("wagrf");
 * 4、当线程没有设置名字时,默认的名字有什么规律:
 *      Thread-0
 *      Thread-1
 *      Thread-2
 */
public class ThreadTest03 {
    
    

     /* public void doSome(){
            this.getName();
            super.getName();
            Thread.currentThread().getName();
        }
        这里的this 和 super 就不行了,但第三种是可以的
      */

    public static void main(String[] args) {
    
    

        //currentThread就是当前线程对象
        //这个代码出现在main方法中,所以当前线程就是主线程
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
        //不加getName是Thread[main,5,main],加了就只是main


        //创建线程对象
        MyThread02 my = new MyThread02();
        System.out.println("默认线程名字:" + my.getName());
        my.setName("xiancheng01");
        System.out.println("修改后线程的名字:" + my.getName());
        my.start();

        System.out.println("------------------");
        MyThread02 my02 = new MyThread02();
        System.out.println("默认线程名字:" + my02.getName());
        System.out.println("修改后线程的名字:" + my02.getName());
        my02.start();

    }
}
class MyThread02 extends Thread{
    
    
    @Override
    public void run() {
    
    
        for (int i = 0; i < 10; i++) {
    
    
            /*
            * currentThread就是当前线程对象,当前线程数是?
            * my调用就是my,my02调用就是my02
            * */
            Thread thread = Thread.currentThread();
            System.out.println(thread.getName() + "----->" + i);


//            下面的方法也可以,但是有一定的局限性
//            System.out.println(this.getName() + "----->" + i);
//            System.out.println(super.getName() + "----->" + i);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_44707513/article/details/110711777