Java 多线程

多线程

  1、什么是进程?什么是线程?
    进程是一个应用程序(1个进程是一个软件)。
    线程是一个进程中的执行场景/执行单元。
    一个进程可以启动多个线程。

  2、对于java程序来说,当在DOS命令窗口中输入:
    java HelloWorld 回车之后。
    会先启动JVM,而JVM就是一个进程。
    JVM再启动一个主线程调用main方法。
    同时再启动一个垃圾回收线程负责看护,回收垃圾。
    最起码,现在的java程序中至少有两个线程并发,
    一个是垃圾回收线程,一个是执行main方法的主线程。

  3、进程和线程是什么关系?举个例子

    阿里巴巴:进程
      马云:阿里巴巴的一个线程
      童文红:阿里巴巴的一个线程

    京东:进程
      强东:京东的一个线程
      妹妹:京东的一个线程

    进程可以看做是现实生活当中的公司。
    线程可以看做是公司当中的某个员工。

    注意:
      进程A和进程B的内存独立不共享。(阿里巴巴和京东资源不会共享的!)
      魔兽游戏是一个进程
      酷狗音乐是一个进程
      这两个进程是独立的,不共享资源。

    线程A和线程B呢?
    在java语言中:
      线程A和线程B,堆内存和方法区内存共享。
      但是栈内存独立,一个线程一个栈。

    假设启动10个线程,会有10个栈空间,每个栈和每个栈之间,
    互不干扰,各自执行各自的,这就是多线程并发。

    火车站,可以看做是一个进程。
    火车站中的每一个售票窗口可以看做是一个线程。
    我在窗口1购票,你可以在窗口2购票,你不需要等我,我也不需要等你。
    所以多线程并发可以提高效率。

    java中之所以有多线程机制,目的就是为了提高程序的处理效率。

  4、思考一个问题:
    使用了多线程机制之后,main方法结束,是不是有可能程序也不会结束。
      main方法结束只是主线程结束了,主栈空了,其它的栈(线程)可能还在压栈弹栈。

  5、分析一个问题:对于单核的CPU来说,真的可以做到真正的多线程并发吗?

    对于多核的CPU电脑来说,真正的多线程并发是没问题的。
    4核CPU表示同一个时间点上,可以真正的有4个进程并发执行。

    什么是真正的多线程并发?
      t1线程执行t1的。
      t2线程执行t2的。
      t1不会影响t2,t2也不会影响t1。这叫做真正的多线程并发。

    单核的CPU表示只有一个大脑:
      不能够做到真正的多线程并发,但是可以做到给人一种“多线程并发”的感觉。
      对于单核的CPU来说,在某一个时间点上实际上只能处理一件事情,但是由于
      CPU的处理速度极快,多个线程之间频繁切换执行,跟人来的感觉是:多个事情同时在做!!!!!
      线程A:播放音乐
      线程B:运行魔兽游戏
      线程A和线程B频繁切换执行,人类会感觉音乐一直在播放,游戏一直在运行,给我们的感觉是同时并发的。


  6、java语言中,实现线程有两种方式,那两种方式呢?

    java支持多线程机制。并且java已经将多线程实现了,我们只需要继承就行了。    

    第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法。    // 定义线程类

    public class MyThread extends Thread{
      public void run(){

      }
    }
    // 创建线程对象
    MyThread t = new MyThread();
    // 启动线程。
    t.start();

    第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法。
    // 定义一个可运行的类
    public class MyRunnable implements Runnable {
    public void run(){

      }
    }
    // 创建线程对象
    Thread t = new Thread(new MyRunnable());
    // 启动线程
    t.start();

    
注意:第二种方式实现接口比较常用,因为一个类实现了接口,它还可以去继承其它的类,更灵活。

  7、关于线程对象的生命周期?
    新建状态
    就绪状态
    运行状态
    阻塞状态
    死亡状态

 

 

 

  

package com.bjpowernode.java.thread;
/*
实现线程的第一种方式:
    编写一个类,直接继承java.lang.Thread,重写run方法。

    怎么创建线程对象? new就行了。
    怎么启动线程呢? 调用线程对象的start()方法。

注意:
    亘古不变的道理:
        方法体当中的代码永远都是自上而下的顺序依次逐行执行的。

以下程序的输出结果有这样的特点:
    有先有后。
    有多有少。
    这是咋回事?这里画一个问号???????????????????????
 */
public class ThreadTest02 {
    public static void main(String[] args) {
        // 这里是main方法,这里的代码属于主线程,在主栈中运行。
        // 新建一个分支线程对象
        MyThread t = new MyThread();
        // 启动线程
        //t.run(); // 不会启动线程,不会分配新的分支栈。(这种方式就是单线程。)
        // start()方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束了。
        // 这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来,start()方法就结束了。线程就启动成功了。
        // 启动成功的线程会自动调用run方法,并且run方法在分支栈的栈底部(压栈)。
        // run方法在分支栈的栈底部,main方法在主栈的栈底部。run和main是平级的。
        t.start();
        // 这里的代码还是运行在主线程中。
        for(int i = 0; i < 1000; i++){
            System.out.println("主线程--->" + i);
        }
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        // 编写程序,这段程序运行在分支线程中(分支栈)。
        for(int i = 0; i < 2000; i++){
            System.out.println("分支线程--->" + i);
        }
    }
}

 

/*
实现线程的第二种方式,编写一个类实现java.lang.Runnable接口。
 */
public class ThreadTest03 {
    public static void main(String[] args) {
        // 创建一个可运行的对象
        //MyRunnable r = new MyRunnable();
        // 将可运行的对象封装成一个线程对象
        //Thread t = new Thread(r);
        Thread t = new Thread(new MyRunnable()); // 合并代码
        // 启动线程
        t.start();

        for(int i = 0; i < 100; i++){
            System.out.println("主线程--->" + i);
        }
    }
}

// 这并不是一个线程类,是一个可运行的类。它还不是一个线程。
class MyRunnable implements Runnable {

    @Override
    public void run() {
        for(int i = 0; i < 100; i++){
            System.out.println("分支线程--->" + i);
        }
    }
}

 

  

posted @ 2020-09-19 20:17  一叶扁舟,乘风破浪  阅读(113)  评论(0编辑  收藏  举报