多线程

1、进程:正在进行的程序

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

一般分为单线程和多线程,单线程就是执行完一个再去执行下一个,多线程是执行一个的同时可以执行下一个,多个线程同时交叉执行。

分时调度是按照cpu的时间划分,抢占式调度是随机分配时间。

 

抢占式调度详解,他是一个多进程并发运行,看着像是“同时运行”但是确实基于cpu使用抢占式调度模式在多线程中高速切换,cpu一时刻只能执行一个线程,但是多个线程并发就让我们感觉到多个同时运行啦。

多线程程序并不能提高程序的运行速度,但是能够提高效率。

 

 

 

 

 

 

就算是一个多线程他仍旧是有一个主线程的,那就是我们压栈的main。

jvm启动后,必然有一个执行路径(线程)main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。

因为本身main方法是从上往下执行,如果一个方法过长,或者某一个出错下面的不能执行。但是有了多线程,就不担心这个啦。

如何执行多线程,有一个单独的类,叫做 Thread

构造方法:

 

 

这个构造方法Thread是为了分配多线程而产生,因为也是类,根据类的操作方式,类名  名称 = new 类型();new的类就是新分配一条线程。

 

 常用方法:

 

 其中,run是线程任务。

两种创建线程方式

1、首先创建一个类,继承Thread类,作为子类,然后重写run方法,在run方法里面写执行内容,并在main里面new Thread ,调用start方法开启线程。

创建线程的步骤:

  • 1 定义一个类继承Thread。
  • 2 重写run方法。
  • 3 创建子类对象,就是创建线程对象。
  • 4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。

  需要注意的是,每一次创建一个线程对象就会在栈里面new一个新栈区,从而让cpu切换调度两个或多个线程。

  

并且我们创建了多个线程对象,Thread线程类为了让我们好区分各个线程,创造两个方法来获取线程名称。

 因为新建类里面直接继承了Thread类,所以在Thread里面可以直接调取类里面方法getName。并且直接在main里面new对象来获取myThread类的地址,通过start来开启线程。

但是mian这个正在执行的方法并不知道自己是线程中的主线程,需要先通过currentThread方法来获取到目前正在执行的main,并且用Thread类 的变量名来接收,从而调取此类下的所有方法,m.getName();

新建类继承Thread
public class MyThread extends Thread{
    //重写run方法,即开启线程任务
        public void run() {
                        for(int i=0;i<50;i++){
                System.out.println(getName()+":"+i);
            }
        }
main方法开启线程,并书写主线程 for
public static void main(String[] args) {
        //普通方法调取run,还是单线程,先走run
        MyThread mt=new MyThread();
        //不能调取run
        //mt.run();
        //开启线程
        mt.start();
        MyThread mt1=new MyThread();//一个代表一个线程
        mt1.start();
        
        Thread m=Thread.currentThread();
        //主线程  main
        for(int i=0;i<50;i++){
            System.out.println(m.getName()+"---"+i);
        }
    }

}

 第二种开启线程方式--Runnable接口

实现步骤:自定义类实现Runnable接口,覆盖掉接口中的run方法,然后测试类中创建Thread对象,将子类Runnable子类线程对象作为参数传入Thread构造函数中,开启start方法。

  1. 1、定义类实现Runnable接口。
  2. 2、覆盖接口中的run方法。。
  3. 3、创建Thread类的对象
  4. 4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
  5. 5、调用Thread类的start方法开启线程。

  

package com.oracle.demo1;

public class MyRunable implements Runnable {

    public void run() {
        for(int i=0;i<50;i++){
            //匿名对象直接静态获取调取父类方法.getName
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

测试类:
    public static void main(String[] args) {
        //创建线程任务对象
        MyRunable mr=new MyRunable();
        MyRunable mr1=new MyRunable();
        //创建Thread对象 将自定义线程对象作为参数传递到Threa构造方法中。
        Thread th=new Thread(mr);
        Thread th1=new Thread(mr1);
        //开启线程
        th.start();
        th1.start();
        for( int i=0;i<50;i++){
            System.out.println(Thread.currentThread().getName()+"--"+i);
        }

 

ps:使用Runnable的好处,首先是避免了java单继承的规则,因为Runnable是接口,第二,将线程分为了线程对象和线程任务,更符合面向对象的原理,第三,避免继承Thread的耦合性,让程序更为灵活,实现解耦。

 第三种开启方式----匿名内部类与多线程。

匿名内部类与多线程的好处是,利用多态的向上转型,父类对象指向子类对象,匿名内部类自有的重写父类,创建子类对象,从而避免了创建一个自定义类,直接在主线程main里面实现从上往下的多线程效果。

    //匿名内部类   创建的是一个Runnable方法
               //这里的Runnable是一个接口不能new,所以new的不是对象,而匿名对象new 的是父类或者接口,Runnable r接收的便是它的重写的子类。
        //Runnable r的接口来接收它的Runnable实现类
        Runnable r=new Runnable(){
            public void run() {
                System.out.println("我是匿名线程任务");
            }
    };
    Thread th2=new Thread(r);
    th2.start();            

 

posted @ 2019-09-03 09:10  lvyimin  阅读(278)  评论(0编辑  收藏  举报