• Java第三阶段学习(六、多线程)


    一、进程和线程的区别:

    进程:正在运行的程序,当一个程序进入内存运行,就变成一个进程。

    线程:线程是进程的一个执行单元。

    总结:一个程序运行后至少会有一个进程一个进程可以有多个线程

    多线程:多线程就是一个程序有多个线程在进行

    多线程程序与单线程程序的区别:

    单线程程序:若有多个任务同时执行,只能执行完上一个程序后,才可以执行下一个程序。

    多线程程序:若有多个程序可以同时执行。

    二、程序运行原理

    1.分时调度CPU为线程平均分配使用时间,所有线程轮流使用CPU

    2.抢占式调度:优先让优先级高的线程使用,若优先级相同随机选择一个线程使用,Java使用的就是抢占式调度。例如:当同时打开多个软件程序的时候,会感觉是在同时运行,其实这个时候,CPU是在多个程序之间高速切换。

    结论:多线程并不会提高程序的运行速率,但能够提高的运行效率,让CPU的效率更高效,使用率更高。

    三、主线程

    package com.oracle.Demo01;
    
    public class Demo02 {
    //main的主线程
        //程序从上到下执行的过程
        //Demo02在编译运行的时候,会启动JVM,运行Demo02,main,找OS去开线程
        //对于你CPU来说有了一个执行路径,运行main方法路径有个名字叫"main",也就是主线程
        //thread:线程
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            for(int i=0;i<1000000;i++){
                System.out.println(i);
            }
            System.out.println("这是最后一句话");
        }
    
    }

    当运行以上代码时,只有在将数字打印完毕后,才会打印“这是最后一句话”,这是因为jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程

    四、Thread类  (线程类)

    1、创建线程类的两种方法:

    1.1继承Thread类:

    步骤:1.创建一个类继承自Thread类

       2.重写run方法

       3.创建子类对象,就是创建线程对象

       4.调用.start()方法,开启线程并让线程执行,并且告诉JVM去执行run方法

    自定义类:

    package com.oracle.Demo02;
    //用继承Thread类的方式创建线程方式
    public class MyThread extends Thread{
        public void run() {
            for(int i=0;i<100;i++){
                System.out.println("这是新建的线程"+i);
            }
        }
    }

    测试类:

    package com.oracle.Demo02;
    
    public class Test {
        //JVM去找OS开了俩线程
        //对于你的CPU来说就有了两条路径,这两条路径都会被CPU执行,CPU有自己选择的权利,所以会出现随机性的结果,
        //你也可以理解为是两个线程在抢夺CPU的资源(时间)
    //OS:系统程序
        public static void main(String[] args) {
            MyThread my=new MyThread();
            my.start();
            for(int i=0;i<100;i++){
                System.out.println("这是主线程"+i);
            }
        }
    }

    调用run()方法和调用start()方法的区别:调用run方法不会开启新线程,调用start会开启新线程

    1.2实现Runnable接口:

    步骤:1、定义类实现Runnable接口。

          2、覆盖接口中的run方法。。

          3、创建Thread类的对象

          4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。

          5、调用Thread类的start方法开启线程。

    自定义类:

    package com.oracle.Demo03;
    //通过实现Runnable接口,创建新线程
    public class RunThread implements Runnable{
        public void run() {
            for(int i=0;i<10;i++){
                System.out.println(i);
            }
            
        }
    
    }

    测试类:

    package com.oracle.Demo03;
    //通过实现Runnable接口的方法来开启新线程
    public class Test4 {
        public static void main(String[] args) {
            Thread t=new Thread(new RunThread());
            t.start();
            for(int i=0;i<10;i++){
                System.out.println("main"+i);
            }
        }
    }

    1.3多线程的内存图解

    多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。

    当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。

    总结:每一个线程都是在内存中开一块新的内存区,并不会在旧的线程后面排队

     1.4获取线程名称的方法:

     

    1.Thread.currentThread()获取当前线程对象

    2.Thread.currentThread().getName();获取当前线程对象的名称

     1.5线程的匿名内部类使用

    package com.oracle.Demo04;
    //线程匿名内部类
    public class Demo01 {
        public static void main(String[] args) {
            //匿名内部类的前提:必须要有继承或实现
            //格式: new 父类或接口(){
    //                要重写的方法;
    //        }.方法();
            //1.继承Thread类的匿名对象
            new Thread(){
                public void run() {
                    for(int i=0;i<5;i++){
                        System.out.println("Thread"+i);
                    }
                }
            }.start();
            //2.实现Runnable接口的匿名内部类
            Runnable r=new Runnable(){
                public void run() {
                    for(int i=0;i<5;i++){
                        System.out.println("Runnable"+i);
                    }
                    
                }
                
            };
            Thread t=new Thread(r);
            t.start();
        }
    }
  • 相关阅读:
    属性的自动完成
    二十七、详测 Generics Collections TDictionary(3): TPairEnumerator、TKeyEnumerator、TValueEnumerator、ExtractPair
    Delphi 反转内存的函数
    类方法调用
    九、泛型排序器 TComparer
    十九、详测 Generics Collections TList (10): OnNotify 事件
    二十、详测 Generics Collections TList (11): Create
    二十一、详测 Generics Collections TQueue (1): Enqueue、Dequeue、Peek
    十四、详测 Generics Collections TList (5): Move、Exchange
    二十二、详测 Generics Collections TQueue (2): Create、Count、Clear、TrimExcess
  • 原文地址:https://www.cnblogs.com/0328dongbin/p/9253137.html
Copyright © 2020-2023  润新知