zoukankan      html  css  js  c++  java
  • 线程

    多线程

    我们在之前,学习的程序在没有跳转语句的前提下,都是由上至下依次执行,那现在想要设计一个程序,边打游戏边听歌,怎么设计?

    要解决上述问题,咱们得使用多进程或者多线程来解决.

    4.1 并发与并行

    • 并发:指两个或多个事件在同一个时间段内发生。

    • 并行:指两个或多个事件在同一时刻发生(同时发生)。

    • 并行与并发

     

    在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 CPU 系统中,每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的。

    而在多个 CPU 系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行。目前电脑市场上说的多核 CPU,便是多核处理器,核 越多,并行处理的程序越多,能大大的提高电脑运行的效率。

    注意:单核处理器的计算机肯定是不能并行的处理多个任务的,只能是多个任务在单个CPU上并发运行。同理,线程也是一样的,从宏观角度上理解线程是并行运行的,但是从微观角度上分析却是串行运行的,即一个线程一个线程的去运行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为线程调度。

    4.2 线程与进程

    • 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。

    • 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

      简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

    我们可以再电脑底部任务栏,右键----->打开任务管理器,可以查看当前任务的进程:

    进程

    进程概念

     

    线程概念线程

     

    线程调度:

    • 分时调度

      所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

    • 抢占式调度

      优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

      • 设置线程的优先级

      设置线程优先级

      • 抢占式调度详解

        大部分操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个程序。比如:现在我们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。此时,这些程序是在同时运行,”感觉这些软件好像在同一时刻运行着“。

        实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。 其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。

        抢占式调度

    4.3 创建线程类

    Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。Java中通过继承Thread类来创建启动多线程的步骤如下:

    1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

    2. 创建Thread子类的实例,即创建了线程对象

    3. 调用线程对象的start()方法来启动该线程

    代码如下:

    测试类:

    public class Demo01 {
    public static void main(String[] args) {
    //创建自定义线程对象
    MyThread mt = new MyThread("新的线程!");
    //开启新线程
    mt.start();
    //在主方法中执行for循环
    for (int i = 0; i < 10; i++) {
    System.out.println("main线程!"+i);
    }
    }
    }

    自定义线程类:

    public class MyThread extends Thread {
    //定义指定线程名称的构造方法
    public MyThread(String name) {
    //调用父类的String参数的构造方法,指定线程的名称
    super(name);
    }
    /**
    * 重写run方法,完成该线程执行的逻辑
    */
    @Override
    public void run() {
    for (int i = 0; i < 10; i++) {
    System.out.println(getName()+":正在执行!"+i);
    }
    }
    }

    获取线程的名称:

    1.使用Thread类中的方法getName() ​ String getName() 返回该线程的名称。 ​ 2.可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称 ​ static Thread currentThread() 返回对当前正在执行的线程对象的引用。

    package com.itheima.demo01.getName;
    // 定义一个Thread类的子类
    public class MyThread extends Thread{
       //重写Thread类中的run方法,设置线程任务
       @Override
       public void run() {
           //获取线程名称
           //String name = getName();
           //System.out.println(name);

           //Thread t = Thread.currentThread();
           //System.out.println(t);//Thread[Thread-0,5,main]
           //String name = t.getName();
           //System.out.println(name);

           //链式编程
           System.out.println(Thread.currentThread().getName());
      }
    }

    线程的名称: 主线程: main 新线程: Thread-0,Thread-1,Thread-2

    package com.itheima.demo01.getName;
    public class Demo01GetThreadName {
       public static void main(String[] args) {
           //创建Thread类的子类对象
           MyThread mt = new MyThread();
           //调用start方法,开启新线程,执行run方法
           mt.start();

           new MyThread().start();
           new MyThread().start();

           //链式编程
           System.out.println(Thread.currentThread().getName());
      }
    }

    设置线程的名称:(了解) 1.使用Thread类中的方法setName(名字) void setName(String name) 改变线程名称,使之与参数 name 相同。 2.创建一个带参数的构造方法,参数传递线程的名称;调用父类的带参构造方法,把线程名称传递给父类,让父类(Thread)给子线程起一个名字 Thread(String name) 分配新的 Thread 对象。

    main类

    public class Demo01SetThreadName {
       public static void main(String[] args) {
           //开启多线程
           MyThread mt = new MyThread();
           mt.setName("小强");
           mt.start();

           //开启多线程
           new MyThread("旺财").start();
      }

    子类

    package com.itheima.demo02.setName;
    public class MyThread extends Thread{

       public MyThread(){}

       public MyThread(String name){
           super(name);//把线程名称传递给父类,让父类(Thread)给子线程起一个名字
      }

       @Override
       public void run() {
           //获取线程的名称
           System.out.println(Thread.currentThread().getName());
      }
    }

    设置线程暂停时间

    public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。 毫秒数结束之后,线程继续执行

    package com.itheima.demo03.sleep;
    public class Demo01Sleep {
       public static void main(String[] args) {
           //模拟秒表
           for (int i = 1; i <=60 ; i++) {
               System.out.println(i);

               //使用Thread类的sleep方法让程序睡眠1秒钟
               try {
                   Thread.sleep(1000);
              } catch (InterruptedException e) {
                   e.printStackTrace();
              }
          }

    创建线程类第二种 -Runnable接口

    创建多线程程序的第二种方式:实现Runnable接口 ​ java.lang.Runnable ​ Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。 ​ java.lang.Thread类的构造方法 ​ Thread(Runnable target) 分配新的 Thread 对象。 ​ Thread(Runnable target, String name) 分配新的 Thread 对象。

    实现步骤:****

    1.创建一个Runnable接口的实现类 ​ 2.在实现类中重写Runnable接口的run方法,设置线程任务 ​ 3.创建一个Runnable接口的实现类对象 ​ 4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象 ​ 5.调用Thread类中的start方法,开启新的线程执行run方法

    实现Runnable接口创建多线程程序的好处: 1.避免了单继承的局限性 一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类 实现了Runnable接口,还可以继承其他的类,实现其他的接口 2.增强了程序的扩展性,降低了程序的耦合性(解耦) 实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦) 实现类中,重写了run方法:用来设置线程任务 创建Thread类对象,调用start方法:用来开启新线程

    package com.itheima.demo04.Runnable;

    public class Demo01Runnable {
       public static void main(String[] args) {
           //3.创建一个Runnable接口的实现类对象
           RunnableImpl run = new RunnableImpl();
           //4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
           //Thread t = new Thread(run);//打印线程名称
           Thread t = new Thread(new RunnableImpl2());//打印HelloWorld
           //5.调用Thread类中的start方法,开启新的线程执行run方法
           t.start();

           for (int i = 0; i <20 ; i++) {
               System.out.println(Thread.currentThread().getName()+"-->"+i);
          }
      }
    }
    package com.itheima.demo04.Runnable;
    //1.创建一个Runnable接口的实现类
    public class RunnableImpl implements Runnable{
       //2.在实现类中重写Runnable接口的run方法,设置线程任务
       @Override
       public void run() {
           for (int i = 0; i <20 ; i++) {
               System.out.println(Thread.currentThread().getName()+"-->"+i);
          }
      }
    }

    Runnable2

    package com.itheima.demo04.Runnable;
    //1.创建一个Runnable接口的实现类
    public class RunnableImpl2 implements Runnable{
       //2.在实现类中重写Runnable接口的run方法,设置线程任务
       @Override
       public void run() {
           for (int i = 0; i <20 ; i++) {
               System.out.println("HelloWorld"+i);
          }
      }
    }

    匿名内部类方式实现线程的创建

    匿名:没有名字 内部类:写在其他类内部的类

    匿名内部类作用:简化代码 把子类继承父类,重写父类的方法,创建子类对象合一步完成 把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成 匿名内部类的最终产物:子类/实现类对象,而这个类没有名字

    格式: new 父类/接口(){ 重复父类/接口中的方法 };

    package com.itheima.demo05.InnerClassThread;

    public class Demo01InnerClassThread {
       public static void main(String[] args) {
           //线程的父类是Thread
           // new MyThread().start();
           new Thread(){
               //重写run方法,设置线程任务
               @Override
               public void run() {
                   for (int i = 0; i <20 ; i++) {
                       System.out.println(Thread.currentThread().getName()+"-->"+"黑马");
                  }
              }
          }.start();

           //线程的接口Runnable
           //Runnable r = new RunnableImpl();//多态
           Runnable r = new Runnable(){
               //重写run方法,设置线程任务
               @Override
               public void run() {
                   for (int i = 0; i <20 ; i++) {
                       System.out.println(Thread.currentThread().getName()+"-->"+"程序员");
                  }
              }
          };
           new Thread(r).start();

           //简化接口的方式
           new Thread(new Runnable(){
               //重写run方法,设置线程任务
               @Override
               public void run() {
                   for (int i = 0; i <20 ; i++) {
                       System.out.println(Thread.currentThread().getName()+"-->"+"传智播客");
                  }
              }
          }).start();
      }
    }
  • 相关阅读:
    PythonのTkinter基本原理
    使用 Word (VBA) 分割长图到多页
    如何使用 Shebang Line (Python 虚拟环境)
    将常用的 VBScript 脚本放到任务栏 (Pin VBScript to Taskbar)
    关于 VBScript 中的 CreateObject
    Windows Scripting Host (WSH) 是什么?
    Component Object Model (COM) 是什么?
    IOS 打开中文 html 文件,显示乱码的问题
    科技发展时间线(Technology Timeline)
    列置换密码
  • 原文地址:https://www.cnblogs.com/Lilwhat/p/12512398.html
Copyright © 2011-2022 走看看