zoukankan      html  css  js  c++  java
  • 2018-08-25多线程Thread类+Runnable接口+线程的6种状态

    多线程:

    进程:进程指正在运行的程序;确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能(进入内存运行的程序成为进程)!

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

    单线程程序:若有多个任务只能依次执行(这个任务执行完毕,下一个任务开始执行)!如:去网吧上网,网吧只能让一个人上网,当这个人下机后,下一个人才能上网(这个任务进站执行完毕,弹栈之后,下一个任务才可以执行)!

    多线程程序:若有多个任务可以同时执行!如:去网吧上网,网吧能够让多个人同时上网(一个线程建一个栈,多个栈内的任务同时执行,Main方法也是一个栈)!

    //八核十六线程的CPU:一个核心有16个线程!

    程序运行原理:

    分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间(比如360安全卫士有3个功能:杀毒,电脑清理,系统修复,这三个功能会被JVM分配1微秒的时间片,轮流执行1微秒,看起来像是同时执行,但实际并不是)!

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

    //可以通过Windwos系统的任务管理器(Ctrl键+Shift键+Esc键调出)设置进程的优先级:

    实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换(分配时间片)!对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行,其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高(单核单线程只能这个任务执行完毕再执行下一个任务,现在多核多线程可以多个任务同时执行,节省时间)!

    主线程:Main方法就是主线程!

    JVM启动后必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在Java中称之为主线程!当程序的主线程执行时,如果遇到了循环而导致程序在指定位置停留时间过长,则无法马上执行下面的程序,需要等待循环结束后能够执行!

    Thread类:

    //第2个构造方法的String name是用来指定线程的名称!

    常用方法:

    //start()方法会调用继承自Thread类的子类重写之后的run()方法(如果直接使用Thread子类的对象调用重写后的run()方法,不会开启线程,就是普通的对象调用方法,所以想要开启线程用start()方法)!

    //sleep()方法:让该线程休眠,即结束进程!

    强调:

    Thread t1 = new Thread();

    t1.start();

    //这样做没有错,但是该start()调用的是Thread类中的run()方法,而这个run()方法没有做什么事情,更重要的是这个run方法中并没有定义我们需要让线程执行的代码!

    每一个线程都有一个独立的内存中的栈空间,所以可以实现并发执行(又要牵扯到管理高并发的问题):

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

    //获取当前执行的线程的对象或名称:

    //由于这个方法是静态的,所以可以类名.方法调用!

    课堂示例代码:

    package com.oracle.duoxiancheng;
    public class Demo01 {
        public static void main(String[] args) {
            //thread新建的线程,和Main方法都是线程,Main方法是主线程,在内存中享有独立的栈空间:
            //新建第一个线程:
            MyThread mt1=new MyThread();
            //开启该线程(调用run()方法):
            mt1.start();
            //新建第二一个线程:
            MyThread mt2=new MyThread();
            //开启该线程(调用run()方法):
            mt2.start();
            for(int i=0;i<1000;++i){
                System.out.println("main……"+i);
            }
            System.out.println("程序结束了!");
            //查看main方法线程名字:
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    package com.oracle.duoxiancheng;
    public class MyThread extends Thread {
        public void run() {
            System.out.println(super.getName());
            //重写run方法,把并发执行的代码放在里面,run方法不需要程序员调用,线程对象的.start()方法:
            for(int j=0;j<1000;++j){
                System.out.println("run……"+j);
            }
        }
    }

    创建线程方式—实现Runnable接口:

    创建线程的另一种方法是声明实现 Runnable 接口的类!该类然后实现 run 方法,然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程!

    //好处:把任务体(Runnable中的run()方法)跟创建线程和开启线程(Thread和start()方法)分离开了!

    Thread类的构造方法:

    //可以传入一个Runnable对象,以及一个线程名字!

    创建线程的步骤:

    1;定义类实现Runnable接口!

    2;覆盖接口中的run方法!

    3;创建Thread类的对象!

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

    5;调用Thread类的start()方法开启线程!

    通过Runnable和Thread方法 来实现创建开启线程的好处:

    ①    实现Runnable接口,避免了继承Thread类的单继承局限性!覆盖Runnable接口中的run方法,将线程任务代码定义到run方法中!

    ②    更加符合面向对象思想,实现了线程任务和线程对象的解耦!

    //下方TIMED_WAITING应该是WAITING,其中Wait()和Notify()是属于Object类!

    示例代码:

    package com.oracle.duoxiancheng;
    public class Demo01 {
        public static void main(String[] args) {
            //thread新建的线程,和Main方法都是线程,Main方法是主线程,在内存中享有独立的栈空间:
            //新建第一个线程,设置线程名称方法②,MyThread重写了Thread的构造方法:
            MyThread mt1=new MyThread("诸葛鬼才");
            //开启该线程(调用run()方法):
            mt1.start();
            //新建第二一个线程:
            MyThread mt2=new MyThread();
            //设置线程名称方法①:
            mt2.setName("蔡文姬");
            //开启该线程(调用run()方法):
            mt2.start();
            /*for(int i=0;i<1000;++i){
                System.out.println("main……"+i);
            }*/
            System.out.println("程序结束了!");
            //查看main方法线程名字:
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    package com.oracle.duoxiancheng;
    public class MyThread extends Thread {
        public MyThread(String getName){
            super(getName);
        }
        public MyThread(){
            
        }
        public void run() {
            System.out.println(super.getName());
            //重写run方法,把并发执行的代码放在里面,run方法不需要程序员调用,线程对象的.start()方法:
            /*for(int j=0;j<1000;++j){
                System.out.println("run……"+j);
            }*/
        }
    }
    
    通过Runnable接口和Thread对象开启线程:
    package com.oracle.duoxiancheng;
    public class Demo02 {
        public static void main(String[] args) throws InterruptedException {
            //runnable实现类任务的编写:
            MyRunnable mr=new MyRunnable();
            //Thread负责创建线程并开启线程
            Thread th1=new Thread(mr);
            th1.start();
            for(int i=0;i<50;++i){
                //休眠可以自己醒:
                Thread.sleep(5000);
                System.out.println("main……"+i);
            }
        }
    }
    
    package com.oracle.duoxiancheng;
    public class MyRunnable implements Runnable {
        public void run(){
            for(int i=0;i<50;++i){
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("这个是run()方法内的……"+i);
            }
        }
    }
    
    匿名对象创建并开启线程:
    package com.oracle.duoxiancheng;
    public class Demo03 {
        public static void main(String[] args) {
            //匿名内部类,下面的new Thread是Thread的子类,只不过没有名字:
            new Thread(){
                public void run(){
                    for(int i=0;i<50;++i){
                        System.out.println("Run……"+i);
                    }
                }
            }.start();
            
            //匿名内部类,匿名new Thread对象里面放一个匿名内部类(Runnable的子类):
            new Thread(new Runnable(){
                public void run(){
                    for(int i=0;i<50;++i){
                        System.out.println("Run……"+i);
                    }
                }
            }).start();
            
            //匿名内部类,new Runnable(){}部分是Runable的子类,前面的Runnable ra=是多态,传入Thread子类对象的构造方法:
            Runnable ra=new Runnable(){
                public void run(){
                    for(int i=0;i<50;++i){
                        System.out.println("Run……"+i);
                    }
                }
            };
            Thread ta=new Thread(ra);
        }
    }
  • 相关阅读:
    使用 RemObjects SDK 建立 WebService 应用
    Excel文件读写的.NET开源组件 Koogra Excel BIFF/XLSX Reader Library
    DataSnap 2009 系列之三 (生命周期篇)
    更改SQL Server表所有者的操作方法
    delphi调用cmd的两种方法
    用AndroidX86和VirtualBox打造高性能Android开发环境
    DevExpress 换肤
    Remobjects关于Channel is Busy 错误的解决方法
    关于D7“System.pas not found”错误的解决方法
    40 套漂亮的图标
  • 原文地址:https://www.cnblogs.com/postgredingdangniu/p/9534519.html
Copyright © 2011-2022 走看看