zoukankan      html  css  js  c++  java
  • Java中的线程

    一、概述进程与线程

    进程:就是正在运行的程序。
    进程是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。

    意义:单进程的计算机只能做一件事情,而我们现在的计算机都可以做多件事情。举例:一边玩游戏(游戏进程),一边听音乐(音乐进程)。也就是说现在的计算机是支持多进程的,以在一个时间段内执行多个任务,并且,可以提交CPU的使用率。

    线程:是程序的执行单元,执行路径。是程序使用CPU的最基本单位。
    单线程:如果程序只有一条执行路径。
    多线程:如果程序有多条执行路径。

    意义:多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。程序的执行其实都是在抢CPU的资源,CPU的执行权。多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢到CPU的执行权。是不敢保证哪一个线程能够在哪个时刻抢到,所以线程的执行有随机性。

    二、线程的理解

    1、线程的两种调度模型

    (1)分时调度模型

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

    (2)抢占式调度模型

    优先让优先级高的线程使用CPU,若果线程的优先级相同,那么会随机选择一个,优先级搞的线程获取的CPU时间戳相对多一些

    Java使用的是抢占式的调度模型

    2、线程的生命周期

    三。线程的创建方式

    (1)继承Thread类。

    步骤:
     A:自定义类MyThread继承Thread类。
    B:MyThread类里面重写run()?
    C:创建对象
    D:启动线程

     1 /*
     2  * 该类要重写run()方法,为什么呢?
     3  * 不是类中的所有代码都需要被线程执行的。
     4  * 而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码。
     5  */
     6 public class MyThread extends Thread {
     7 
     8     @Override
     9     public void run() {
    10         // 一般来说,被线程执行的代码肯定是比较耗时的。所以我们用循环改进
    11         for (int x = 0; x < 200; x++) {
    12             System.out.println(x);
    13         }
    14     }
    15 }
    16 
    17 public static void main(String[] args) {
    18     // 面试题:run()和start()的区别?
    19     // run():仅仅是封装被线程执行的代码,直接调用是普通方法
    20     // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。
    21     // 创建两个线程对象
    22     MyThread my1 = new MyThread();
    23     MyThread my2 = new MyThread();
    24 
    25     my1.start();
    26     my2.start();
    27 }

    Thread类的一些方法:

    如何获取线程对象的名称呢?
    public final String getName():获取线程的名称。
    如何设置线程对象的名称呢?
    public final void setName(String name):设置线程的名称

    针对不是Thread类的子类中如何获取线程对象名称呢?
    public static Thread currentThread():返回当前正在执行的线程对象
    Thread.currentThread().getName()

    public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。
    当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。

    public final void join():等待该线程终止。

    public static void yield():暂停当前正在执行的线程对象,并执行其他线程。

    public final void stop():让线程停止,过时了,但是还可以使用。
    public void interrupt():中断线程。 把线程的状态终止,并抛出一个InterruptedException。

    public static void sleep(long millis) 线程休眠

    如何获取线程对象的优先级?
    public final int getPriority():返回线程对象的优先级
    如何设置线程对象的优先级呢?
    public final void setPriority(int newPriority):更改线程的优先级。
    注意:
    线程默认优先级是5。
    线程优先级的范围是:1-10。
    线程优先级高仅仅表示线程获取的 CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到比较好的效果。

    (2)实现Runnable接口

    步骤:
    A:自定义类MyRunnable实现Runnable接口
    B:重写run()方法
    C:创建MyRunnable类的对象
    D:创建Thread类的对象,并把C步骤的对象作为构造参数传递

     1 public class MyRunnable implements Runnable {
     2 
     3     @Override
     4     public void run() {
     5         for (int x = 0; x < 100; x++) {
     6             // 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
     7             System.out.println(Thread.currentThread().getName() + ":" + x);
     8         }
     9     }
    10 
    11 }
    12 
    13   public static void main(String[] args) {
    14         // 创建MyRunnable类的对象
    15         MyRunnable my = new MyRunnable();
    16 
    17         // 创建Thread类的对象,并把C步骤的对象作为构造参数传递
    18         // Thread(Runnable target)
    19         // Thread t1 = new Thread(my);
    20         // Thread t2 = new Thread(my);
    21         // t1.setName("林青霞");
    22         // t2.setName("刘意");
    23 
    24         // Thread(Runnable target, String name)
    25         Thread t1 = new Thread(my, "林青霞");
    26         Thread t2 = new Thread(my, "刘意");
    27 
    28         t1.start();
    29         t2.start();
    30     }

    实现Runnable接口的好处:

    (1)可以避免由于Java单继承带来的局限性

    (2)适合多个相同的程序去处理同一个资源的情况,把线程同程序的代码,数据有效的分离,较好的提现了面向对象的设计思想

    经典的值得思考的简单代码:(2019-05-27 21:48:00 继续写)

     1 // 大体结构是这样的: 创建Thread对象:new Thread(创建Runnable对象:new Runnable(){ 执行Runnable的run()方法 }){ 执行Thread的run()方法 }.start(); 执行start方法
     2 new Thread(new Runnable(){
     3             @Override
     4             public void run() {
     5                 while (true) {
     6                     try {
     7                         Thread.sleep(500);
     8                     } catch (InterruptedException e) {
     9                         e.printStackTrace();
    10                     }
    11                     System.out.println("Runnable:" + Thread.currentThread().getName());
    12                 }
    13             }
    14             
    15         }){
    16             @Override
    17             public void run() {
    18                 while (true) {
    19                     try {
    20                         Thread.sleep(500);
    21                     } catch (InterruptedException e) {
    22                         e.printStackTrace();
    23                     }
    24                     System.out.println("Thread:" + Thread.currentThread().getName());
    25                 }
    26             };
    27             
    28         }.start();

    之所以说这个例子比较经典,是因为你要搞懂这个到底在运行哪个run()方法,其实是在执行Thread类的run()方法,因为这个是重写Thread类的run()方法,只有在没有重写Thread类的run()方法的时候,才会去执行父类的run()方法,可以看下Thread类的源码:

    1  private Runnable target;
    2    
    3  @Override
    4     public void run() {
    5         if (target != null) {
    6             target.run();
    7         }
    8     }
  • 相关阅读:
    Libcurl
    Inno Setup教程
    APICloud平台的融云2.0集成
    关于mysql建立索引 复合索引 索引类型
    linux恢复误删除文件-extundelete
    OpenStack QA
    Android之应用程序怎样调用支付宝接口
    NYOJ 22 素数求和问题
    Mycat(5):聊天消息表数据库按月分表实践,平滑扩展
    opencv对图像进行边缘及角点检測
  • 原文地址:https://www.cnblogs.com/ssh-html/p/10068180.html
Copyright © 2011-2022 走看看