java多线程Thread

认识多线程,首先要从程序是如何在CPU中进行调度说起,众所周知,我们自己的笔记本中只有一个CPU,这个CPU在你电脑开机的时候开始就执行着许多程序,比如操作系统,可是一个CPU在某一单位时间只能运行一个程序,而电脑中这么多的程序CPU是如何安排工作的呢?这就涉及到了并发的概念.
并发:有两种情况:
- 多个软件同时运行
- 同一个软件在同一时刻被多个用户同时请求

为了满足并发这一要求,计算机必须对程序和CPU作出调整,以实现并发.
那么在只有一个核和一块CPU的前提下计算机是怎么做的呢?

  • 操作系统将CPU划分成很多的时间片段
  • 操作系统将程序划分为进程

    操作系统将一个个进程按照优先级安排进CPU,当一个进程停止工作的时候,另一个进程立马上去,使得CPU马不停蹄的工作,可是这样还不够,为了更大程度的提高CPU的利用率,每个进程还被分成了许许多多的线程,分的单位越小,CPU被浪费的机会就越少,这样我们的目的也就到了,即累死CPU.

这儿来正式的介绍一下进程和线程的概念:

-进程: process 是一块包含了某些资源的内存区域,操作系统软件利用进程把软件程序分割成若干个单元,这个单元就叫进程.
进程在CPU上的上下操作很浪费时间,但是必须存在这种情况,为了能够让CPU的利用率更高,给进程再细分为若干线程.
实际上在CPU上上下的是线程.
- 线程:Thread 进程中所包含的一个或多个执行的单元,称为线程.
进程还拥有一个私有的虚拟内存地址空间,该空间仅能被他包含的线程访问.线程只能归属一个进程,并且他只能访问该进程的所有资源,
当操作系统创建了一个进程后,该进程就会自动申请一个名为主线程或者叫首要线程的线程.
同类的多个线程共享一个块内存空间和一组资源,线程本身有一个供程序执行的堆栈,线程在切换时负荷小,
因此线程被称之为轻负荷进程,一个进程可以包含多个线程

再来聊聊进程和线程的区别:

  • 一个进程至少有一个线程
  • 线程的划分尺度小于进程,使得多个线程并发性高
  • 另外,进程在指定过程中拥有独立的内存单元,而多个线程共享进程的内存空间,从而极大的提高了程序的运行效率
  • 线程在执行过程中与进程区别在于每个独立的线程有一个程序的运行入口,顺序执行序列和程序出口
  • 单线程不可以独立运行,由应用程序提供对线程的控制 线程实际上是一个执行单元(run方法),run不能独立运行,必须依赖进程

    线程的使用场景:

  • 线程通常用于在一个应用程序中需要同时完成多个任务的情况,我们可以将每个任务定义一个线程,使得他们可以一同工作.

  • 也可以用于在单一线程中完成,但是使用多线程可以更快的完成所需要的功能.

但我们脑子中有了关于线程的知识框架之后就可以进行使用了
线程的使用有两种方法,
方案一:继承Thread类

  • 此类是线程类,其每一个实例对象表示一个可以并发运行的线程,我们可以通过继承此类,并重写run方法,来定义一个具体的线程/
  • run方法中体现的是线程的功能,(线程的入口和线程的出口),启动线程时调用线程对象的start方法,而不是直接调用run方法,

  • start方法将当前线程纳入线程调度,是当前线程可以并发运行,当线程获取CPU时间片段之后,开始自动运行run方法中的逻辑
    示例如下:`

public class MyThread1 extends Thread{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("MyThread1.run方法");
    }

}`

(通过main方法进行测试)
注意:线程类的测试只能在main方法中运行,不可以在Junit框架下测试

public class Demo {
    public static void main(String[] args) {
        MyThread1 mt1=new MyThread1();
        mt1.run();//可以调用run方法,但不是线程并发,这是错误的调用方式
        mt1.start();//把mt1线程放到内存中,但是不一定调用run()
        MyThread1 mt2=new MyThread1();
        mt2.start();
    }
}

方案二:实现Runnable接口

  • :实现此接口并重写run方法来定义线程类,然后在创建线程的时候,将runnable接口的实例传入并启动线程

  • 这样做的好处可以将线程和线程要执行的任务分离,减少耦合,同时java是单继承,定义一个实现Runnable

  • 接口,这样的做法可以更好地去实现其他接口和继承父类

/**
 * 方案二:实现自Runnable接口
 * @author 李旭康
 *
 */
public class MyThread1 implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("Runnable MyThread1.run方法");
    }

}

测试类如下:`

public class Demo {
    public static void main(String[] args) {
        MyThread1 mt1=new MyThread1();
        Thread t1=new Thread(mt1);
        t1.start();

        Thread t2=new Thread(mt1);
        t2.start();
    }
}
`

这里需要注意一下,虽然这两种方式都可以实现多线程的调用,但是在实际开发的时候采用的大部分还是方案二,因为方案一是继承Thread类,继承是单继承,而方案二是实现Runnable接口,实现是多实现,采用方案而大大提高了程序的可扩展性.

今天主要讲解多线程的概念,关于多线程的具体使用以及常用API将会在下篇文章中做出详细讲解.

猜你喜欢

转载自blog.csdn.net/qq_36239350/article/details/81986298