zoukankan      html  css  js  c++  java
  • Javase之多线程(1)

    多线程(1)

    多线程的概述

    了解多线程之前需要先了解线程,而线程依赖于进程而存在,所以先了解进程。

    什么是进程

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

    什么是线程

    在一个进程中又可以执行多个任务。而每一个任务,就可以看成是一个线程。

    线程:是程序的执行基本单元,执行路径,是程序使用CPU的最基本单位。

    单线程:程序只有一条执行路径。

    多线程:程序有多条执行路径。

    多线程的意义

    多线程的存在,不是为了提高程序的执行速度。而是为了提高程序的使用率。

    程序的执行其实是在抢CPU的资源,CPU的执行权。

    多个进程在抢CPU资源,而如果其中某一个进程如果执行路径较多,其抢到CPU执行权的几率也就较高。

    我们是不敢保证哪一个线程在哪个时刻能抢到CPU的执行权,所以线程的执行有随机性。

    并发和并行

    并发:逻辑上同时发生,指在某一时刻同时运行多个程序。(可以理解为一个CPU同时执行多个任务,那么我们称为并发)

    并行:物理上同时发生,指在某一时刻同时运行多个程序。(可以理解为,多个CPU同时执行多个任务,而每一个CPU只执行了一个任务,那么称这些程序并行发生)

    Java程序的运行原理·

    由Java命令启动JVM,JVM启动就相当于启动一个进程。接着创建一个主线程,去调用main方法。

    问题:JVM虚拟机是多线程还是单线程?

    多线程。因为在JVM启动主线程时,垃圾回收线程也要先启动,否则就会出现内存溢出问题,所以当JVM启动时,最低启动了两个线程。所以JVM是多线程的。

    如何启动多线程

    多线程是依赖于进程存在的,所以要想实现多线程就得创建一个进程。而进程是由系统调用的,所以应该先调用系统功能创建一个进程。

    Java是不能直接调用系统功能的,所以是没有办法直接实现多线程程序。

    但是Java可以通过调用c/c++写好的程序来实现多线程程序,由c/c++去调用系统功能创建进程,然后由Java调用这些东西,然后提供一些类来使用就可以实现多线程程序。

    Java提供Theard类实现多线程,而实现多线程的方法有两种

    一.继承Theard类

    步骤:

    ​ 1。自定义类继承Theard类。

    ​ 2.在自定义类中重写run()方法。

    ​ 为什么要重写run()方法?因为不是所以的代码都要被线程执行,为了区分哪些代码需要被线程执行,Java就提供Theard类中的run()方法来包含被线程执行的代码。

    ​ 3.创建对象。

    ​ 4.调用start()方法了,启动线程。

    class myTheard extends Thread{
        public myTheard(){}
         public myTheard(String name){
            super(name);
         }
    
        @Override
        public void run() {
            for (int i = 0;i < 100;i++){
                System.out.println(this.getName()+":"+i);
            }
        }
    }
    
    public class theardtest {
        public static void main(String[] args) {
            myTheard my = new myTheard();    
            my.start();
            
            myTheard my2 = new myTheard();       
            my2.start();
        }
    }
    
    run()和start()的区别

    run():仅仅是封装被线程执行代码;

    start():首先启动线程,再由JVM调用该线程的run()方法。

    如何设置线程对象名称
    public final String getName():返回线程名称。
    
    public final void setName(String name):设置线程名称
    

    1.通过对象调用setName()方法修改

     myTheard my = new myTheard();
            my.setName("线程1");
    

    2.修改构造方法通过调用父类中的构造来给线程对象修改名称

    class myTheard extends Thread{
        public myTheard(){}
         public myTheard(String name){
            super(name);
         }
    
        @Override
        public void run() {
            for (int i = 0;i < 100;i++){
                System.out.println(this.getName()+":"+i);
            }
        }
    }
    
    public class theardtest {
        public static void main(String[] args) {
            myTheard my = new myTheard("线程00001");
            myTheard my1 = new myTheard("线程000002");
            my.start();
            my1.start();
        }
    }
    
    如何获得main方法的线程名称
    public static Thread currentThread():返回对当前正在执行的线程对象的引用。
    public final String getName():返回线程名称。
    
    Thread.currentThread().getName()
        
    eg:
    System.out.println(Thread.currentThread().getName());
    out:
    main
    

    线程调度

    在只有一个CPU的情况下,一个CPU在某一时刻只能执行一条指令,线程只有得到CPU时间片,即使用权,才能执行指令。有两种调度模型。

    线程的两种调度模型

    1.分时调度模型

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

    2.抢占式调度模型

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

    Java中的线程调度

    Java是抢占式调度模型。所以每个Java线程都有优先级。

    Java线程中即使没有去设置优先级,它也有默认的优先级。

    Java优先级有关的方法有两个
    public final int getPriority():返回线程的优先级。 
    
    public final void setPriority(int newPriority):更改线程的优先级。 
    
    注意

    线程默认优先级为5

    线程优先级范围是:1—10

    线程的优先级仅仅表示线程获取CPU时间片的几率高,但不一定保证优先级高的线程先执行,因为CPU的调度是随机的。即在次数比较多,或多次运行程序才会看到优先级高的效果。

    对线程的控制

    1.线程休眠
    public static void sleep(long millis) throws InterruptedException:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响
    

    在线程的操作内调用该方法用。

    线程加入
    public final void join() throws InterruptedException:等待该线程终止。
    

    让使用该方法的线程执行完毕在执行其他线程。

    注意:该方法的调用位于线程开启之后。

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

    yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU时间。注意:放弃的时间不确定,可能一会就会重新获得CPU时间片。让多个线程执行更和谐但不能保证一人一次。

    后台线程
    public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
    

    即其他非后台线程运行完成后,后台线程自动结束。通过isAlive()方法判断其他线程的是否存活。

    终止线程
    public final void stop():已过时。 该方法具有固有的不安全性让。线程停止。
    
    public void interrupt():中断线程。 把线程状态终止并抛出一个异常
    
  • 相关阅读:
    9.经典进程同步问题
    8.信号量
    7.进程同步之临界区问题
    6.CPU调度
    AIX 10G HA RAC卸载
    HP11.31安装11.2.0.3实施手册
    AIX上安装oracle10g
    习水医院12C RAC 数据库安装文档
    linux 11201(11203) ASM RAC 安装
    如果一个节点重新安装了,处理办法
  • 原文地址:https://www.cnblogs.com/wf614/p/11673844.html
Copyright © 2011-2022 走看看