java线程

本文详细解释了程序、进程、线程的概念,比较了单核CPU和多核CPU在并发处理上的差异,介绍了线程的创建方式(继承Thread和实现Runnable/Callable接口),以及start()和run()方法的区别。此外,还讨论了FutureTask在并发编程中的作用和线程常用方法如setName、getName和getId。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

程序:即program,它是一个特定的任务,用某一程序语言编写的一组指令集合,是一段静态的代码。

进程:即process,它是一次执行的过程,或称为正在运行的一个程序,是一个动态的过程,有一整从创建到销毁的生命周期。

线程:即thread,它是进程的细化,是程序内部的一条自执行路径;有以下特点:

  • 一个进程可以有多个线程。
  • 一个进程同一时间并行执行多个线程,就是支持多线程。
  • 线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小。
  • 一个进程中的多个线程共享相同的内存单元/内存地址空间,它们从同一个堆中分配对象;可以访问相同的变量和对象,这就使得线程间的通信简便、高效,多个线程操作共享的系统资源可能会带来安全隐患。

单核cpu:是一种假的多线程,在同一个时间单元内,它只能自执行一个线程的任务,通过切换线程来执行不多线程的任务,因为cpu时间切换短所以感觉不出来。

多核cpu:cpu多核能同时运行的线程数较单核更多,有利于同时运行多个程序。执行速度不同,更加流畅。

并行:多个cpu同时执行多个任务。

并发:一个cpu(采用时间切片)同时执行多个任务。

线程创建

通过继承Thread类,然后重写run方法创建

package org.example;

import java.text.DateFormat;

class PrimeThread extends Thread {
    long mainPrime;

    PrimeThread(long mainPrime) {
        this.mainPrime = mainPrime;
    }

    @Override
    public void run() {
       while (true) {
            System.out.println(Thread.currentThread().getName()+"run..." + DateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
            try {
                Thread.sleep(mainPrime);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public  class  ThreadMain{
    public static void main(String[] args) {
        PrimeThread primeThread = new  PrimeThread(2000);
        primeThread.start();
    }
}

start方法的作用:开始执行当前线程,java虚拟机当前线程的run方法。

run方法的作用:线程类的run方法是Runnable接口的一个抽象方法,由java虚拟机直接调用的,不会创建的新线程。

start()方法和run()方法的区别:start方法在java.lang.Thread类中定义;而run方法在java.lang.Runnable接口中定义,必须在实现类中重写。

线程的创建过程:当调用start方法时,程序会创建一个新的线程,然后由java虚拟机直接调用run方法,如果直接调用run方法,则不会创建线程,而是一个普通的方法调用。

实现Runnable接口

package org.example;

import java.text.DateFormat;

class RunnableThread implements  Runnable {
    long mainPrime;

    RunnableThread(long mainPrime){
        this.mainPrime=mainPrime;
    }

    @Override
    public void run() {
       while (true) {
            System.out.println(Thread.currentThread().getName()+"run..." + DateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
            try {
                Thread.sleep(mainPrime);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class RunnableMain {
    public static void main(String[] args) {
        new Thread(new RunnableThread(2000)).start();
    }
}

使用实现Runnable接口好处:可以将线程(Thread)和线程任务(RunnableThread)分离。

实现Callable接口

package org.example;

import java.text.DateFormat;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

class CallableThread implements Callable {
    long mainPrime;

    CallableThread(long mainPrime) {
        this.mainPrime = mainPrime;
    }

    @Override
    public Object call() throws Exception {
        while (true) {
            System.out.println(Thread.currentThread().getName()+"run..." + DateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
            try {
                Thread.sleep(mainPrime);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class CallableMain {
    public static void main(String[] args) {
        CallableThread callableThread = new CallableThread(2000);
        //将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
        FutureTask futureTask = new FutureTask<>(callableThread);
        //将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
        new Thread(futureTask).start();

    }
}

FutureTask:FutureTask类实现了RunnableFuture接口,而RunnnableFuture接口继承了Runnable和Future接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。FutureTask可以用来包装Callable或者Runnbale对象。因为FutureTask实现了Runnable接口,所以FutureTask也可以被提交给Executor。

线程中的常用方法

start:开始执行当前线程,java虚拟机当前线程的run方法。

run:线程类的run方法是Runnable接口的一个抽象方法,由java虚拟机直接调用的,不会创建的新线程。

setName:设置线程名字,必须在线程启动前设置,例如:

Thread thread = new Thread(futureTask);
thread.setName("thread1");
thread.start();

getName:获取当前线程的名称,也可以通过线程的构造方法设置,例如:

 PrimeThread primeThread = new  PrimeThread(2000);
 primeThread.setName("thread2");
 primeThread.start();

 System.out.println(primeThread.getName());

getId:获取当前线程的id,例如:

PrimeThread primeThread = new  PrimeThread(2000);
primeThread.setName("thread2");
primeThread.start();

System.out.println(primeThread.getId());

currentThread:获取当前线程的native静态方法,通过该方法会返回一个线程对象,源代码:

  public static native Thread currentThread();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河马开源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值