Java中线程的三种实现方式

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情


      Java中使用Thread代表线程类,所有的线程类都必须是Thread类或者其子类的实例。每个线程的作用就是完成一定的任务,即执行一段程序流。Java中使用线程执行体来表示这段程序流


Java中线程的实现方式有如下三种:

1.继承Thread类

public class Thread extends Object implements Runnable

定义Thread类的子类,并重写Thread类的run()方法,创建子类对象(即线程对象),调用线程对象的start()方法来启动该线程。eg:

public class ThreadDemo extends Thread {

	private int i;
	public void run(){
		for(; i<100 ;i++){
			System.out.println(getName() +" "+ i);
		}
	}
	public static void main(String[] args) {
		for(int i = 0 ;i<100; i++){
                        //currentThread是Thread类的静态方法,该方法返回当前正在执行的线程对象
                        //getName()返回当前线程对象的名字
                        System.out.println(Thread.currentThread().getName()+" "+i);
			if(i==20){
				//启动两个线程,但是实际上有三个线程,即main主线程
                                //用户启动的多个线程的名字依次为Thread-0、Thread-1、、、、
                                new ThreadDemo().start();
				new ThreadDemo().start();
			}
		}

	}

}

注意:该例中第一次出现的变量i是实例变量,而每次创建线程对象时候,Thread-0和Thread-1两个线程对象不能共享实例变量i。即使用继承Thread方法创建线程对象时,多个线程之间无法共享线程类的实例变量。


2.实现Runnable接口

public interface Runnable

定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法同样是该线程的执行体。创建该Runnable实现类的实例,并将此实例作为Thread的target(即构造函数中的参数)来创建Thread对象(该Thread对象才是真正的线程对象,只是该Thread对象负责执行其target的run()方法)。最后调用线程对象的start()方法来启动该线程。eg:

public class ThreadDemo implements Runnable {

	private int i;
	<strong>public void run</strong>(){
		for(; i<100 ;i++){
			//当线程类实现Runnable接口时,只能通过Thread.currentThread()方法获得当前线程
			System.out.println(Thread.currentThread().getName() +" "+ i);
		}
	}
	public static void main(String[] args) {
		for(int i = 0 ;i<100; i++){
			System.out.println(Thread.currentThread().getName()+" "+i);
			if(i==20){
				ThreadDemo td = new ThreadDemo();
				//创建两个Thread对象,并且均把Runnable接口实例对象作为target
				new Thread(td).start();
				new Thread(td).start();
			}
		}

	}

}

从运行的结果可以看到实例变量i的输出是连续的。也就是使用Runnable接口创建的多个线程是可以共享线程类的实例变量,这是因为多个线程可以共享同一个target,所以多个线程可以共享同一个线程类(target类)的实例属性。

3.使用Callable和Future

public interface Future<V> 

public interface Callable<V>

public interfaceRunnableFuture<V> extends Runnable, Future<V>

public class FutureTask<V>extends Object implementsRunnableFuture<V>

      Java5之后,提供了Callable接口,看起来像是Runnable接口的增强版:该接口提供call()方法来作为线程执行体。与run()相比,call()方法更强大,该方法可以有返回值,并且可以声明抛出异常

     但是Callable不是Runnable接口的子类,不能作为Thread的target。而且call()方法返回的值如何调用呢?

     Java5给出了Future接口,来获得call()方法的返回值。并提供了FutureTask实现类,该类实现了Runnale接口和Future接口---可以作为Thread类的target。

     创建并启动有返回值的线程的步骤如下:

     创建Callable接口的实现类,并实现call()方法,该方法有返回值;创建Callable实现类的实例,使用FutureTask来包装Callable对象,并且也封装了call()方法的返回值;使用FutureTask作为Thread类的target创建并启动线程;调用FutureTask对象的get()方法返回子线程执行结束后的返回值。

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

public class CallableDemo implements Callable<Integer>{
	//实现call()方法,作为线程执行体
	public Integer call(){
		int i = 5;
		for( ; i<100 ; i++){
			System.out.println(Thread.currentThread().getName() + "的循环变量i的值:" +i);
		}
		//call()方法可以有返回值
		return i;
	}
	public static void main(String[] args) {
		//创建Callable对象
		CallableDemo cd = new CallableDemo();
		//使用FutureTask来包装Callable对象
		FutureTask<Integer> task = new FutureTask<Integer>(cd);
		for(int i=0 ; i<100 ; i++){
			System.out.println(Thread.currentThread().getName() + "的循环变量i的值:" +i);
			if(i==20){
				//实质还是以Callable对象来创建并启动线程
				new Thread(task,"有返回值的线程").start();
			}
		}
		try{
			System.out.println("子线程的返回值" + task.get());
			
		}catch(Exception e){
			e.printStackTrace();
		}

	}

}

 FutureTask是Future接口的实现类。Future接口提供了一些方法来控制他关联的Callable任务。

booleancancel(boolean mayInterruptIfRunning)
Attempts to cancel execution of this task. //视图取消该Future关联的Callable任务
Vget()
Waits if necessary for the computation to complete, and then retrieves its result.
//返回call()方法的返回值,调用该方法将导致程序阻塞,必须等到子线程结束后才会有返回值
Vget(long timeout, TimeUnit unit)
Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.
//设置阻塞时间
booleanisCancelled()
Returns true if this task was cancelled before it completed normally.
booleanisDone()
Returns true if this task completed.
Callable有泛型限制,Callable接口里的泛型形参类型与Call()方法返回值类型相同。


4.创建线程的三种方式对比

实现Runnable和Callable接口的方法基本相同,只不过Callable接口定义的方法可以有返回值,而且可以声明抛出异常而已。

因此采用实现Runnable和Callable接口方式创建多线程——

优势:

1.线程类只是实现了接口类,还可以继承其他类

2.在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程类处理同一份资源的情况。

劣势:

编程稍稍复杂,如果要访问当前线程必须使用Thread.currentThread()方法

而继承Thread方式则与之相反,因为已经继承了Thread类,不能再继承其他类。编写简单,如果要访问当前线程,直接使用this即可获得当前线程。

故一般建议采用实现Runnable、Callable接口的方式实现多线程。

java线程三种实现方式线程池使用详解 线程三种实现方式 继承Thread类 实现Runnable接口 实现Callable接口 线程安全问题 卖车票案例 解决线程安全 同步代码块 同步方法 同步锁(Lock锁) 线程池的使用 Excutors创建多线程 ExecutorService创建多线程(常用子类ThreadPoolExecutor) 多线程中workQueue任务队列集中使用类型 拒绝策略 ThreadFactory自定义线程创建 ThreadPoolExecutor扩展 线程线程数量 阅读详情

相关推荐

Java基础之线程实现三种方式

Java基础之线程实现三种方式

李长渊的博客 2569

Java线程实现三种方式

Java线程实现三种方式

crg18438610577的博客 1816

Java线程】多线程三种实现方式和多线程常用方法

在main()方法中,你可以创建和启动额外的线程,这些线程称为子线程。子线程可以并行执行,与主线程同时进行。多线程三种实现方式如下: 继承Thread类的方式进行实现 实现Runnable接口的方式进行实现 利用Callable接口和Future接口方式实现

m0_65277261的博客 5077

Java 实现线程三种方式

两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。线程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。...

Crush258_的博客 2723

java中线三种实现方式

一下记录下线程的3中实现方式:Thread,Runnable,Callable 不需要返回值时,建议使用Runnable;有返回值时建议使用Callable 代码如下所示: package com.four.day01; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionExcep...

weixin_34029680的博客 170

java如何实现线程_java中线三种实现方式

packagecom.four.day01;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;/*** 此处主要是实现线程三种方式* 1.继承Thread类* 2.实现runnable接口* 3.实现Call...

weixin_42500380的博客 621

线程概述以及Java中线三种创建方式(继承Thread类、实现Runnable接口、实现Callable接口)

线程是一个序内部的一条执行流序如果只有一条执行流,那么这个序就是单线程序多线程是指从软硬件上实现的多条执行流的技术(多条线程由CPU负责调度执行)如:12306同时处理多个用户请求,百度网盘下载文件的同时上传文件;再例如:消息通信、淘宝、京东系统都离不开多线程技术。

后端小白个人学习记录 395

java中创建线程三种方式

java中线创建的三种方式 什么是线程:一段代码在特定数据集合上的一次运行活动,操作系统资源分配的基本单位。(换了个数据集合或者换了代码都不算是同一个进线程:是进中的一个实体,本身是不会独立存在的。是进的一个执行路径,一个进中至少有一个线程,进的多个线程共享进的资源。任务调度和执行的基本单位。 操作系统中大概是这样的: 在JVM中,这个图可以再细化一下,大概是这样的:...

qq_43100957的博客 211

线程三种实现方式

Java中线实现三种方式,分别是继承Thread类、实现Runnable接口和实现Callable接口。 继承Thread类 Thread类是Java.lang包中的一个类,从这个类中实例化的对象代表线程序员启动一个新的线程需要建立Thread类的实例。 Thread类中两个常用的构造方法是: public Thread()//创建一个新的线程对象 Public Thread(Strin...

is_Javaer的博客 5915

Java执行线程任务的三种方式(带案例)

目录 一、线程、进和内存 二、Java执行线程任务的三种方式 1、直接继承Thread 2、实现Runnable接口 3、实现Callable接口 一、线程、进和内存 线程和进是系统进行资源分配和调度的基本单位,一个进中至少有一个线程,进中的多个线程共享进的资源。线程是进中的一个实体,线程是不会独立存在的! 所以说,没有进就就没有线程。 对于CPU资源比较特殊,线程才是CPU分配的基本单位。 main函数启动 ——>JVM进 ——>main函数线程

swadian2008的博客 3346

【温故而知新】Java中线实现方式

大家好,欢迎来到小蒋聊技术,小蒋准备和大家一起聊聊技术的那些事。大家常说金九银十毕业季,又是毕业生求职的好时机。虽然最近几年计算机行业不那么景气,但是为什么还是有大量人想要加入?想要求职的进入计算机行业的小伙伴们,大家千万不要被网上的只言片语、悲观情绪所左右,一定要有自己的思考和判断。小蒋带着大家换一个角度来看看,每年行业平均从业人员数量和人员的平均工资的排行,你会发现计算机行业的就业机会和工资排名远远超过80%的行业。那网上大家纠结抱怨的到底是什么呢?

小蒋聊技术 315

线程实现三种方式

实现Runnable接口。实现callable接口。

qq_34534731的博客 203

Java 中创建线程几种方式

Java中,线程(Thread)是序执行的最小单元,它允许序在同一时间执行多个任务。Java中的线程可以由Thread类创建,也可以通过实现Runnable接口或Callable接口创建。: 线程对象已经被创建,但还没有调用start()方法。: 线程已经调用了start()方法,但还没有获得CPU时间片执行。可运行状态包括了操作系统线程的就绪(Ready)和运行(Running)状态。: 线程因为等待监视器锁而被阻塞,无法继续执行。: 线程通过调用wait()join()

精神小牛马 1466

Java中线调用2次start方法会发生什么

由于Java语言规定,一个线程在它的生命周期中只能启动一次,如果再次调用该线程的start()方法,则JVM会抛出一个非法线程状态的异常。4:等待/超时等待(wait/time wait)线程调用wait或者sleep后处于的状态。2:就绪(Runnable)在线程调用start方法后,还未被cpu调度的状态。5:阻塞(Blocking)线程因未获取到锁,或者处于IO状态等原因处于的状态。3:运行(Running)处于就绪状态的线程被CPU调度后的状态。此时线程进入就绪状态并等待CPU的调度。

m0_73651612的博客 487

Java中线创建的三种方式

Java中创建线程三种方法

白茶 278

Java并发编线程三种实现方式

 一.进线程的区别及关系   1.线程是进内的一个执行单元;进至少有一个线程;它们共享进的地址空间;而进有自己独立的地址空间。 2.资源拥有:进是资源分配和拥有的单位,同一个进内的线程共享进的资源。 3.线程是处理器调度的基本单位,但进不是。 4.二者均可并发执行,因此也会出现并发问题,需要做并发控制。 5.只有多核cpu才能实现真正意义上的多线程,单核cpu只...

lcgoing的博客 404

实现线程三种方式以及线程安全

  Java中使用Thread代表线程类,所有的线程类都必须是Thread类或者其子类的实例。每个线程的作用就是完成一定的任务,即执行一段序流。Java中使用线程执行体来表示这段序流。 Java中线实现方式有如下三种: 1.继承Thread类   定义Thread类的子类,并重写Thread类的run()方法,创建子类对象(即线程对象),调用线程对象的start()方法来启动该线程。 package com.example; public class ThreadDemo extends Thre

weixin_43946462的博客 524

java线程间通信的方式

java线程间通信的方式1. 共享变量2. 等待/通知3. 管道流 1. 共享变量 volatile修饰的变量,线程间可见,可使用这种变量作为线程间传递消息的媒介; 延伸出来的,还有redis中的值,数据库中的值,都可以作为线程间共同访问的变量; 2. 等待/通知 同步代码中利用锁对象的wait和notify方法来进行通信; 经典案例如thread.join()方法,里面就是用等待通知机制实现的; 3. 管道流 管道输入/输出流和普通的文件输入/输出流或者网络输入/输出流不同之处在于,它主要用于线

没啥简介 5673
上一篇: 初识Bootstrap
下一篇: MyEclipse+Tomcat6.0+JDK1.6
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值