创建线程的两种方式

先来了解一下与线程相关的概念,如程序,进程,以及他们之间的区别

1)、程序Program:

程序是一段静态的代码, 它是应用程序执行的蓝本。

2)、进程Process

进程是指一种正在运行的程序, 有自己的地址空间。

3)、线程Thread

进程内部的一个执行单元, 它是程序中一个单一的顺序控制流程。线程又被称为轻量级进程(lightweight process)。如果在一个进程中同时运行了多个线程, 用来完成不同的工作, 则称之为多线程。
线程的特点:

  • 轻量级进程
  • 独立调度的基本单位
  • 可并发执行
  • 共享进程资源
4)、进程与线程的区别
区别进程线程
根本区别作为资源分配的最小单位作为资源调度和执行的最小单位
开 销每个进程都有独立的代码和数据空间(进程上下文), 进程间的切换会有较大的开销。线程可以看成时轻量级的进程, 同一类线程共享代码和数据空间, 每个线程有独立的运行栈和程序计数器(PC), 线程切换的开销小。
所处环境在操作系统中能同时运行多个任务(程序)在同一应用程序中有多个顺序流同时执行
分配内存系统在运行的时候会为每个进程分配不同的内存区域除了CPU之外, 不会为线程分配内存(线程所使用的资源是它所属的进程的资源) , 线程组只能共享资源
包含关系没有线程的进程是可以被看作单线程的, 如果一个进程内拥有多个线程, 则执行过程不是一条线的, 而是多条线(线程) 共同完成的。线程是进程的一部分, 所以线程有的时候被称为是轻权进程或者轻量级进程。
5)、线程的生命周期

(json插队方法,属于对象 t1.join()表示必须等到t1线程执行完,才执行其他线程,t1执行的时候,其他线程都是属于阻塞状态)

1、新生状态 (一旦开启了新生状态,线程就有了自己的工作空间)

2、就绪状态(等待cpu调度,调用start方法)yield让出cpu的调度直接从运行状态转换到就绪状态、时间片用完由运行变就绪状态、jvm算法切换

3、运行状态(cpu调度到改线程)

4、阻塞状态(如,执行sleep方法,wait,或同步代码锁、join方法)

5、死亡状态(线程正常执行完毕,或者调用stop方法【不推荐,线程不安全】,通过标识符 使用terminate方法)


1)、创建线程的第一种方式:

继承Thread类,重写run方法

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("当前线程的名字--->"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
		//创建4个线程
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        MyThread t4 = new MyThread();
	//开启线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();

        System.out.println("当前线程的名字--->"+Thread.currentThread().getName());
    }
}

输出结果:

当前线程的名字--->main
当前线程的名字--->Thread-0
当前线程的名字--->Thread-1
当前线程的名字--->Thread-3
当前线程的名字--->Thread-2

这里线程的执行顺序并不是按照我们 执行start()的顺序,因为start()方法,并不是代表立即去执行线程,只不过是告诉cpu我可以被调度,至于它先执行哪个线程,要靠cpu去决定。(但是我们可以设置一个优先级,优先级高的显被执行的概率大,但是不是绝对的)

2)、创建线程的第二种方式:

实现Runnable接口。重写run方法

public class MyRanableThread implements Runnable
{
    @Override
    public void run() {
        System.out.println("当前线程的名字--->"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {

        Thread t1 = new Thread(new MyRanableThread());
        t1.start();
        new Thread(new MyRanableThread()).start();
        new Thread(new MyRanableThread()).start();
        new Thread(new MyRanableThread()).start();
    }
}

执行结果:

当前线程的名字--->Thread-2
当前线程的名字--->Thread-0
当前线程的名字--->Thread-1
当前线程的名字--->Thread-3

通过Thread的构造方法传入Runnable接口的实现类,然后执行start()方法,开启线程,相对于第一种方式,这里的Thread其实就是个静态代理对象。
那么两种的方式有什么区别呢
执行了start()方法之后,当线程被cpu调度之后,就会执行run()方法,进入Thread这个类,看一下run()方法的源码(部分):

class Thread implements Runnable //thread类其实也是实现了Ruanable接口
	
	   /* What will be run. */
    private Runnable target;
    
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

原来当我们使用第一种方法 继承Thread类,重写run方法,在调用run方法的时候,必然就会调用子类重写的run方法,然后执行。但当我用第二种方法,也就是Thread构造传入Runnable接口的实现类之后,当我们要执行run方法,会先判断target是否为空,然后执行target.run(),也就是我们实现Runnable时候所重写的run方法。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值