多线程:线程与进程、线程的实现方式、生命周期、常用API

线程的概念

程序:Program,一个指令的集合。

进程:Process,正在执行的程序
进程是程序的一次静态态执行过程,占用特定的地址空间。
每个进程都是独立的,由cpu,data,code三部分组成
缺点:内存的浪费, cpu的负担

线程:是进程中一个“单一的连续控制流程”
线程又称为轻量级进程(lightweight process)
线程们同时运行,彼此独立。
一个进程可以拥有多个并行(concurrent)的线程。
一个进程中的线程共享相同的内存单元/内存地址空间 -> 可以访问相同的变量和对象,而且它们从同一堆中分配对象 -> 通信、数据交换、同步操作。
由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这使得通信更简便而且信息传递的速度也更快。

一个进程至少有一个线程,比如迅雷,N个下载任务可以同时进行,迅雷是一个进程,每一个下载任务是一个线程。
各个应用程序(QQ, IDEA…)会去抢占CPU资源,在同一个时间点上,CPU只能处理一个应用程序,看上去貌似是同时执行,实际上是CPU在快速的切换。
进程抢占到CPU资源后,每个线程再去抢占CPU资源,谁先抢占到就执行谁(所以每次执行顺序都不一样)

Javac与Java
Java虚拟机启动的时候会有一个进程java.exe,该进程至少有一个线程在负责java程序的运行。而且这个线程运行的代码存在于main方法中,该线程称为主线程。
一个进程中的线程共享代码和数据空间。
线程结束,进程不一定结束;但进程结束,线程一定结束。

进程与线程的区别
在这里插入图片描述
Java中的多线程

实现多线程方式一:

  1. 继承Thread类
  2. 重写run方法,指的是核心执行的逻辑
  3. 不要直接调用run(调用run只是执行类的普通方法),而是使用start方法来开启线程(由start再调用run)

测试:

public class demo1 extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 5 ; i++) {
            System.out.println(Thread.currentThread().getName()+"=============="+i);
        }
    }

    public static void main(String[] args) {

        demo1 demo1 = new demo1();
        demo1.start();
        for (int i = 0; i < 5 ; i++) {
            System.out.println(Thread.currentThread().getName()+"=============="+i);
        }
    }
}

输出:

main==============0
main==============1
Thread-0==============0
main==============2
Thread-0==============1
main==============3
Thread-0==============2
main==============4
Thread-0==============3
Thread-0==============4

实现多线程方式二:

使用了代理设计模式

实现Runnable接口

public class demo2 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 5 ; i++) {
            System.out.println(Thread.currentThread().getName()+"=============="+i);
        }
    }

    public static void main(String[] args) {

        demo2 demo2 = new demo2();
        Thread thread = new Thread(demo2);
        thread.start();

        for (int i = 0; i < 5 ; i++) {
            System.out.println(Thread.currentThread().getName()+"=============="+i);
        }
    }
}

最好使用第二种方式,

  1. 因为java是单继承,将继承关系留给最需要的类;
  2. 使用Runnable接口不需要给共享变量添加static关键词,因为只要创建一个对象。

线程的生命周期

  1. 新生状态:
    当创建好当前线程对象之后,没有启动之前(调用start方法之前)
    ThreadDemo thread = new ThreadDemo()
    RunnableDemo run = new RunnableDemo()

  2. 就绪状态:准备开始执行,并没有执行,表示调用start方法之后
    当对应的线程创建完成,且调用start方法之后,所有的线程会添加到一个就绪队列中,所有的线程同时去抢占cpu的资源

  3. 运行状态:当当前进程获取到cpu资源之后,就绪队列中的所有线程会去抢占cpu的资源,谁先抢占到谁先执行,在执行的过程中就叫做运行状态
    抢占到cpu资源,执行代码逻辑开始

  4. 死亡状态:当运行中的线程正常执行完所有的代码逻辑或者因为异常情况导致程序结束叫做死亡状态
    进入的方式:
    1、正常运行完成且结束
    2、人为中断执行,比如使用stop方法
    3、程序抛出未捕获的异常

  5. 阻塞状态:在程序运行过程中,发生某些异常情况,导致当前线程无法再顺利执行下去,此时会进入阻塞状态,进入阻塞状态的原因消除之后,
    所有的阻塞队列会再次进入到就绪状态中,随机抢占cpu的资源,等待执行
    进入的方式:
    sleep方法
    等待io资源
    join方法(代码中执行的逻辑)

常用API

static Thread currentThread()
Returns a reference to the currently executing thread object.
获取当前线程对象

String getName()
Returns this thread’s name.
获取当前线程的名称

long getId()
Returns the identifier of this Thread.
获取当前线程的id

int getPriority()
Returns this thread’s priority.
获取线程的优先级,在一般系统中,范围是0~10,如果没有设置,默认值是5。

void setPriority​(int newPriority)
Changes the priority of this thread.
设置线程的优先级
优先级越高,一定越先执行?
不一定,只是优先执行的概率比较大。

boolean isAlive()
Tests if this thread is alive.
判断线程是否存活

void join()
Waits for this thread to die.
调用该方法的线程强制执行,其他线程处于阻塞状态,该线程执行完毕后,其他线程再执行。

static void sleep​(long millis)
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.
当前执行的线程睡眠mills秒,线程处于阻塞状态。

static void yield()
A hint to the scheduler that the current thread is willing to yield its current use of a processor.
当前正在执行的线程暂停一次,允许其他线程执行,不阻塞,线程进入就绪状态

练习

用两个线程实现交替输出 0~10 的数(利用sleep方法的时间差)

public class test1 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 11; i++) {
            if(i%2!=0) {
                System.out.println(Thread.currentThread().getName() + "-----" + i);
                try {
                    Thread.sleep(1001);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        test1 test1 = new test1();
        Thread thread = new Thread(test1);
        thread.start();

        for (int i = 0; i < 11; i++) {
            if(i%2==0) {
                System.out.println(Thread.currentThread().getName() + "-----" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值