Java多线程之线程的创建、优先级

本文介绍了Java中的多线程概念,包括进程与线程的区别、线程的生命周期、如何创建线程(通过Thread、Runnable、Callable接口)以及线程的优先级和调度器的工作原理。通过示例展示了线程优先级的设置,并指出高优先级线程并不一定先执行。
摘要由CSDN通过智能技术生成

进程

正在运行中的程序。每个进程都拥有自己(独立)的系统资源、内存空间和地址空间

线程

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。

线程的生命周期

新建状态(new )、可运行状态(runnable)、运行状态(running )、阻塞状态(blocked)、终止状态(dead)

  1. 当线程处于新建状态的时候,表明此时线程的对象实例已经被创建,但是尚未取得运行线程所需要的资源
  2. 产生了对象的实例之后,一旦调用线程的start()方法,则线程就会进入可运行状态,表明该线程已经获得运行时所需要的系统资源,具备了被调度执行的条件,从而使该线程可以被调度执行。
  3. 线程的运行状态是指线程被JVM线程调度程序分配了CPU执行时间,使用run() (在执行了start()之后,,run()自启动)方法可以使线程进入运行状态。正在运行的线程随时可能由JVM线程调度程序送回可运行状态。
  4. 当线程的run()方法执行完毕后进入终止状态,处于该状态的线程不会再被调度执行。
  5. 阻塞状态通常用于线程之间的通信与同步控制。

创建线程

Java程序中的线程被设计为一个对象,该对象具有自己的生命周期,可以利用接口java.lang.Runnable、类java.lang.Thread、Callable接口 创建一个线程

通过java.lang.Thread创建线程

继承Thread类,重写 run() 方法(必须重写)


public class ThreadDemo extends Thread {
 
    @Override
    public void run() {
        System.out.println("当前线程的是:"+this.getName());
    }
 
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
    }
 
}
  • 优点:程序代码相对简单,缺点:java 单继承使用场景限制

实现Runnable接口,实现 run() 方法


public class RunnableDemo implements Runnable {
 
    @Override
    public void run() {
        System.out.println("当前线程的是:"+Thread.currentThread().getName());
    }
 
    public static void main(String[] args) {
        RunnableDemo runnableDemo = new RunnableDemo();
        new Thread(runnableDemo).start();
   	 }
    }
 

Runnable创建线程:通过把Runnable的一个子类的实例作为参数传递 给Thread类的一个构造方法

优点:

  1. 符合面向对象的设计思想

从面向对象的设计角度看,Thread类是虚拟CPU 的封装,因而Thread类的子类是关于CPU行为的类,但是在继承Thread类的子类大多都是与CPU不相关的类,而实现Runnable接口的方法将不会影响到Thread体系

  1. 实现了Runnable接口的类可以 用extends继承其他的类

Callable接口创建线程:实现Callable 接口,使用FutureTask 进行包装,通过Thread的构造方法传入futureTask实例

package com.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ICallableTest implements Callable<Long> {
    @Override
    public Long call() {
        Long id = Thread.currentThread().getId();
        System.out.println("当前的线程是"+Thread.currentThread().getName());
        return id;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ICallableTest ct = new ICallableTest();
        FutureTask futureTask = new FutureTask(ct);
        Thread t = new Thread(futureTask,"二货");
        t.start();
        System.out.println(futureTask.get());
    }
}

实现Callable接口的 call() 方法是带返回值(方法体中必须return )的,通过futureTask的 get() 获得

在这里插入图片描述

Callable和Runnable 的区别:

  • Runnable的 run() 方法没有返回值,而Callable得 call() 方法有返回值,且支持泛型
  • Runnable 接口 的 run() 方法只能抛出运行时候得异常,且无法捕获处理;Callable 接口 call 方法允许抛出异常(throws Exception),可以获取异常信息

线程的优先级

线程优先级是指优先级越高,越有可能先执行,但只是建议先执行,具体什么时候执行由系统决定(既不能绝对的说线程的调度是按照优先级进行调度的)

例如在windows系统中,当一个优先级为5且处于可运行状态的线程在等待CPU资源的时,系统可能正在执行一个优先级为3的线程

  • 设置线程的优先级
public final void setPriority(int newPriority)
  • 获取线程的优先级
public final int getPriority( )
  • 在Thread 类中定义了线程优先级的取值范围(1~10)
//静态成员变量
  	public static final int MIN_PRIORITY = 1;


    public static final int NORM_PRIORITY = 5;


    public static final int MAX_PRIORITY = 10;

优先级高只是建议先执行

Priority.java

public class Priority extends Thread {
    public Priority(String s){
        setName(s);
    }
    public void run(){
        System.out.println("线程:"+getName()+"----"+getPriority());
    }
}

PriorityTest.java

public class PriorityTest {
    public static void main(String[] args){
        Priority p1 = new Priority("线程 1");
        Priority p2 = new Priority("线程 2");
        Priority p3 = new Priority("线程 3");
        Priority p4 = new Priority("线程 4");
        p1.setPriority(1);
        p2.setPriority(2);
        p3.setPriority(3);
        p4.setPriority(4);
        p1.start();
        p2.start();
        p3.start();
        p4.start();
    }
}

在这里插入图片描述
在这里插入图片描述

线程调度器

Java提供了一个线程调度器来监视所有程序中的所有运行的线程,并决定哪个线程应该运行,哪个线程应该排队等待。在线程的 调度器的决策过程中,它可以识别线程的两个特征:一个是线程的优先级别,另一个是守护标志

  • 守护线程:一般具有一个较低的优先级别,并且当计算机中运行的线程减少的时,为一个或多个程序提供一项基本的服务。例如垃圾收集线程就是一个不断运行的守护线程,它由于JVM提供,通过扫描程序查找不再被访问的变量,并把这些变量的资源释放给系统
  • 调度器的基本原则:如果只有守护线程在运行,JVM将退出。新线程将从创建它的线程那里继承优先级别和守护标志,调度器通过分析所有线程的优先级来决定哪个线程先运行。具有较高优先级的线程,能够在较低优先级的 线程之前执行(但并不绝对)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值