[Java学习笔记]多线程基础

本文深入解析Java中多线程的实现方式,包括线程的创建、生命周期、优先级设置及守护线程的使用。通过具体示例,阐述了线程的运行机制,对比了Runnable与Callable接口的区别,以及如何通过FutureTask获取线程执行结果。

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

了解进程与线程

  • 进程:简单的理解——进行中的程序,实际上,进程就是我们操作系统进行资源分配的单位,也是程序运行的载体
  • 线程:简单的理解——进程中各种各样的任务,实际上,线程是任务调度的最小单位,一个进程中会有各种的线程在并发执行任务

Java中的线程

  • java.lang.Thread 类,即是java中对于线程的封装对象,.我们想要利用多个线程并发执行不同任务,也正是多线程技术,那么就需要使用Thread类对象

构造器方法:
大体而言实际上就两个

  • Thread()
    分配新的 Thread 对象。

  • Thread(Runnable target)
    分配新的 Thread 对象。

创建Thread线程的方法

  • (1)创建实体类对象继承Thread类并实现run()方法(实际上就是定义了Thread里面的任务)

  • (2)创建实体类对象实现Runnable接口(它就是任务的封装形式)实现其内run方法利用new Thread(Runnable r) 创建Thread对象

  • (3)创建实体类对象实现callable接口创建Thread对象

  • (4)通过匿名内部类直接重写run方法创建Thread对象/Runnable对象(归根结底和前面一样)

多线程的使用

public class ThreadDemo1 {
	public static void main(String[] args) throws InterruptedException {
		ThreadDemo1 a = new ThreadDemo1();
		Thread t1 = a.new Mythread();
		t1.setPriority(10);
		Thread t2 = a.new Mythread();
		
		t1.start();
		t2.start();
		
		for(int i= 0 ; i < 20 ; i ++) {
			System.out.println(Thread.currentThread().getName()+":  "+i);
			Thread.sleep(1);
		}
		
		System.out.println(Thread.currentThread().getName()+"结束");
	}
	private class Mythread extends Thread {
		@Override
		public void run() {
			for(int i = 0 ; i < 20 ; i ++)
			{
				System.out.println(Thread.currentThread().getName()+":	"+i);
			}
			System.out.println(Thread.currentThread().getName()+"结束");
		}
		
	}
}

运行结果如下:总共三个线程——main、Thread-0、Thread1,三个线程结果看来是交替运行的

main: 0
Thread-0: 0
Thread-0: 1
Thread-0: 2
Thread-0: 3
Thread-0: 4
Thread-0: 5
Thread-0: 6
Thread-0: 7
Thread-0: 8
Thread-0: 9
Thread-0: 10
Thread-0: 11
Thread-0: 12
Thread-0: 13
Thread-0: 14
Thread-0: 15
Thread-0: 16
Thread-0: 17
Thread-0: 18
Thread-0: 19
Thread-0结束
Thread-1: 0
Thread-1: 1
Thread-1: 2
Thread-1: 3
Thread-1: 4
Thread-1: 5
main: 1
Thread-1: 6
Thread-1: 7
Thread-1: 8
Thread-1: 9
Thread-1: 10
Thread-1: 11
Thread-1: 12
Thread-1: 13
Thread-1: 14
Thread-1: 15
Thread-1: 16
Thread-1: 17
Thread-1: 18
Thread-1: 19
Thread-1结束
main: 2
main: 3
main: 4
main: 5
main: 6
main: 7
main: 8
main: 9
main: 10
main: 11
main: 12
main: 13
main: 14
main: 15
main: 16
main: 17
main: 18
main: 19
main结束

可能疑惑的问题:

  • 多个线程是怎么运行的呢?为什么运行结果会变成随机交替的?
    线程首先会处于就绪态,只有就绪态的线程才有权力进入运行态(CPU只会给就绪态分配时间片),什么是时间片——时间片就是这个线程被随机分到的能够占用cpu的时间,分配给谁是随机的,分配多少也是随机的!当一个线程时间片过期就会返还至就绪态,若线程任务完成则会进入死亡态

  • 线程重写的不是run方法吗,为什么我们调用的却是start方法?
    start方法作用:开启线程使之进入就绪态,等待CPU分配时间片执行run方法,如果我们直接调用run方法,那么就不是在利用线程机制了,这时仅仅只是调用run方法而已!

Callable接口和Runnable接口实现线程的对比

java.util.concurrent 接口 Callable

  • Callable接口怎么看看都像是Runable接口的增强版,Callable接口提供了一个call()方法可以作为线程任务执行体,但call()方法比run()方法功能更加强大。
  • 1:call()方法可以有返回值
  • 2:call()方法可以声明抛出异常

我们发现,Callable接口并不是Runnable接口的子接口,而是一个独立的新接口,对比Runnable取代了void run()方法的是V call() 方法

  • V call()
    throws Exception
    返回计算的结果,如果无法计算结果,则抛出一个异常。

既然Callable不是Runnable的子接口,那么如何构造Thread对象呢?

有这么一个类

  • public class FutureTask<V.>implements RunnableFuture<V.>
    他实现了Runable接口,因此可以用于构建Thread对象

构造方法摘要

  • FutureTask(Callable callable)
    创建一个 FutureTask,一旦运行就执行给定的 Callable。
    FutureTask(Runnable runnable, V result)
    创建一个 FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。

因此我们可以构造FutureTask对象来构建Thread对象,并通过get方法可以得到任务运行的结果

public class TestCallable {

    public static  void  main(String[] args) {

        CallableDemo callableDemo = new CallableDemo();
       
        //执行Callable方式,需要FutureTask实现类的支持,用于接收运算结果
        FutureTask<Integer> futureTask = new FutureTask<Integer>(callableDemo);
        new Thread(futureTask).start();
		
		Integer sum = futureTask.get();
        System.out.println("计算结果:"+sum);
    }

}

class CallableDemo implements Callable<Integer> {

    @Override

    public Integer call() throws Exception {

        int sum = 0 ;

        for(int i = 0;i <= 100;i++) {

            System.out.println(i);

            sum += i;

        }
        return sum;
    }

}

守护线程的使用

线程可以分为前置线程和守护线程两类

  • 一个进程的结束是进程中所有前置线程的结束,守护线程在前置线程全部转入死亡态时会瞬间被JVM杀死且甚至不会去执行finally语句块内容
public class DaemonTest {
	public static void main(String[] args) {
		Thread t0 = new Thread() {
				public void run() {
					while(true) {
						System.out.println("守护");
						try {
							Thread.sleep(1);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
		};
		Thread t1 = new Thread() {
				public void run() {
					for(int i = 0 ; i < 10 ; i ++) {
						System.out.println(Thread.currentThread().getName()+": " + i);
					}
					System.out.println(Thread.currentThread().getName()+"结束");
				}
		};
		Thread t2 = new Thread() {
				public void run() {
					for(int i = 0 ; i < 10 ; i ++)
					{
						System.out.println(Thread.currentThread().getName()+": " + i);
					}
					System.out.println(Thread.currentThread().getName()+"结束");
				}
		};
		t0.setDaemon(true);
		t0.start();
		t1.start();
		t2.start();
	}
}

结果如下:即便是死循环进程作为守护线程一样在前台线程结束后直接消亡

守护
Thread-1: 0
Thread-1: 1
Thread-1: 2
Thread-1: 3
Thread-1: 4
Thread-1: 5
Thread-1: 6
Thread-1: 7
Thread-1: 8
Thread-1: 9
Thread-1结束
Thread-2: 0
Thread-2: 1
Thread-2: 2
Thread-2: 3
Thread-2: 4
Thread-2: 5
Thread-2: 6
Thread-2: 7
Thread-2: 8
Thread-2: 9
Thread-2结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值