JAVA多线程编程技术
- 格式:doc
- 大小:213.50 KB
- 文档页数:22
多线程并发的书籍以下是多线程并发的相关书籍:1. 《Java多线程编程核心技术》:这本书比较基础,写的比较细,代码示例比较多,包含了线程的基础使用、线程锁的使用(Synchronized和ReentrantLock)、单例模式、定时任务、线程组的相关概念,可以当做工具书来看,缺点就是没有深入底层的实现原理。
2. 《JAVA并发编程:核心方法与框架》:这本书和上一本书是同一个作者写的,所以风格很相似,代码示例比较多,主要介绍了juc包下的各类并发框架的使用,包括CountDownLatch、线程池、Futura、ForkJoin、并发队列等,书中介绍了很多API的使用方式,建议当做工具书使用,缺点是没有深入底层的实现原理。
3. 《Java并发编程实战》:这本书是外国人写的,介绍了Java并发编程的各种算法和实现方式,有点难度。
4. 《多处理器编程的艺术》:这本书介绍了并发编程的各种算法和实现方式,包括Java实现,有点难度。
5. 《并发的艺术》:这本书介绍了多核处理器的共享内存模型中的各种算法和实现方式。
6. 《Java虚拟机并发编程》:这本书介绍了JVM平台上各种语言的并发比较,如Java、Scala、Clojure等。
7. 《实战Java高并发程序设计》:这本书介绍了Java高并发程序设计的实战技巧和经验。
8. 《七周七并发模型》:这本书介绍了七种并发模型的比较和实现方式。
9. 《Go并发编程实战》:这本书介绍了Go语言中的并发编程实现方式。
10. 《事务信息系统》:这本书从数据库层面介绍了并发编程的实现方式。
11. 《C并发编程经典实例》:这本书介绍了C语言中的并发编程实现方式。
12. 《C++ Concurrency in Action》:这本书介绍了C++中的并发编程实现方式。
13. 《Python编程实战:运用设计模式、并发和程序库创建高质量程序》:这本书介绍了Python中并发编程的实现方式。
synchronize实现原理在计算机的操作中,同步(Synchronize)是一个非常重要的概念。
在多线程编程中,同步就是一种技术,用来保证多个线程在访问共享资源的时候,不会发生错误或者冲突,从而保证程序的运行顺利。
synchronize是Java中用于同步的关键字,下面就为大家讲解一下synchronize的实现原理。
1. synchronize的概念在Java中,synchronize可以有两种用法:一种是修饰方法,一种是修饰代码块。
synchronize修饰方法时,它的范围是整个方法;synchronize修饰代码块时,它的范围只是代码块内部。
不管是哪种用法,都是用于同步执行。
2. synchronize的实现原理在Java中,所有的对象都有一个锁,也就是实例对象的锁。
当使用synchronize修饰方法或者代码块时,就是使用了这个对象的锁。
这个锁是由Java虚拟机(JVM)来管理的。
当线程A想要执行一个被synchronize修饰的方法时,它首先会去请求这个对象的锁。
如果这个锁被线程B占用着,那么线程A就会等待,直到这个锁被线程B释放掉。
当线程B释放这个锁以后,线程A 才可以继续执行这个方法。
当线程A执行完这个方法,就会释放这个锁,让其他线程来争抢锁。
这样就可以保证同一时刻只有一个线程在执行这个方法或者代码块。
需要注意的是,当一个线程占用了对象的锁之后,其他线程不会再去尝试占用这个锁,它们只能等待这个锁被释放掉之后才能继续执行。
3. synchronize的优缺点优点:synchronize是一种非常简单、有效的同步机制,它可以帮助我们很容易地管理共享资源的访问。
如果一个线程占用了对象的锁,其他线程就不能修改这个对象的状态,可以避免线程安全问题的出现。
缺点:synchronize的缺点就是效率问题。
虽然synchronize可以保证线程的安全,但它只能让一个线程占用对象的锁。
如果有很多线程都需要访问这个对象,那么只能一个一个地等待,这样会降低程序的效率。
java21开发手册
Java 21开发手册是一本关于Java编程语言的参考书,它详细介绍了Java 21版本中的各种特性和功能。
这本书包括了Java语言的基本语法、面向对象编程、异常处理、多线程编程、网络编程、数据库编程等方面的内容,同时还介绍了Java虚拟机的工作原理和调优方法。
以下是一些Java 21开发手册中的主要内容:
1. Java语言基础:介绍Java语言的基本语法、数据类型、运算符、控制语句等基础知识。
2. 面向对象编程:介绍Java中的类、对象、继承、封装、多态等面向对象编程的概念和技术。
3. 异常处理:介绍Java中的异常机制和异常处理的方法,包括try-catch语句、throw语句、finally语句等。
4. 多线程编程:介绍Java中的多线程编程技术,包括线程的创建、启动、同步、通信等。
5. 网络编程:介绍Java中的网络编程技术,包括Socket编程、HTTP协议、TCP/IP协议等。
6. 数据库编程:介绍Java中的数据库编程技术,包括JDBC接口、SQL语言、事务处理等。
7. Java虚拟机:介绍Java虚拟机的工作原理和调优方法,包括内存管理、垃圾回收、性能优化等。
总之,Java 21开发手册是一本非常实用的Java编程参考书,对于想要深入学习Java编程语言的人来说是一本不可多得的好书。
Java语言多线程技术应用研究作者:林铁瀛来源:《科技创新导报》2011年第11期摘要:多线程编程是Java语言的一个很重要的特点,它是面向对象程序设计的关键技术之一。
本文简要的探讨了Java语言多线程的基本技术,就线程的创建、线程控制和调度及线程同步等处理技术做了相关探讨。
关键词:多线程创建控制同步应用中图分类号:G633.3 文献标识码:A 文章编号:1674-098X(2011)04(b)-0022-01多线程程序是Java语言的一个很重要的特点,在一个Java程序中,可以同时并行运行多个相对独立的线程。
线程是一段完成某个特定功能的语句体,一个线程是一个程序内部单个顺序的控制流。
多线程是指同一个应用程序中,有多个顺序流同时执行,即多线程表示一个程序内部可以同时执行多个线程。
多线程的程序能更好地表述和解决现实世界的问题,是计算机应用开发和设计过程的一个必然发展趋势。
1 线程的创建在Java程序设计中,创建线程有两种方法:一个方法是从一个自定义的类(如Mythread)中创建,即让程序继承Thread类。
例如:Thread t=new Mythread();这个类扩展了Java基础类库中的Thread类及其方法。
Mythread类中必须替换Thread类中的run()方法。
应注意的是,初始化Mythread为类,并不能使对象t作为一个线程开始执行,而必须独立运行的子语句体放到run()方法(是Thread类中的一个方法)中。
再调用线程的star()方法来开始线程的执行,进而依顺序调用run()方法。
这种创建线程的方法有一个缺陷,即必须扩展Thread类。
由于Java是单一继承,不支持多重继承,所以不能写一个多线程的Applet。
因为如果写多线程的Applet的话,就要扩展Applet和Thread类,而这在Java中是不允许的。
由于这个原因,Java给出了另一个创建线程的方法。
另一种方法是使用接口。
一、介绍在Java中,线程的等待是指一个线程暂时停止执行以等待某个条件的触发。
线程的等待通常与锁相关联,当线程等待时,它会释放持有的锁,从而允许其他线程进入临界区。
Java提供了多种方法让线程进入等待状态,本文将为您详细介绍这些方法。
二、w本人t()方法w本人t()方法是Object类中的一个实例方法,它使当前线程进入等待状态,直到其他线程调用notify()或notifyAll()方法唤醒它。
w本人t()方法必须在同步块或同步方法中调用,否则会抛出IllegalMonitorStateException异常。
w本人t()方法也可以指定等待的时间,超过指定时间后线程会自动唤醒。
三、join()方法join()方法是Thread类中的一个实例方法,它使当前线程等待指定线程执行完毕。
当调用join()方法时,当前线程会进入等待状态,直到指定线程执行完毕才会继续执行。
四、sleep()方法sleep()方法是Thread类中的一个静态方法,它使当前线程进入休眠状态,指定的时间过后再重新唤醒。
sleep()方法不会释放锁,因此其他线程无法访问该线程的同步块或同步方法。
五、park()方法park()方法是LockSupport类中的一个静态方法,它使当前线程进入等待状态,直到其他线程调用unpark()方法唤醒它。
与w本人t()方法不同,park()方法不需要在同步块或同步方法中调用。
六、aw本人t()方法aw本人t()方法是Condition接口中的一个实例方法,它使当前线程进入等待状态,直到其他线程调用signal()或signalAll()方法唤醒它。
与w本人t()方法类似,aw本人t()方法必须在Lock对象的控制下调用。
七、总结通过本文的介绍,我们详细了解了Java中让线程进入等待的方法,包括w本人t()、join()、sleep()、park()和aw本人t()等方法。
这些方法各有特点,可以根据实际需求选择合适的方法来实现线程的等待。
JAVA使⽤多线程(线程池)进⾏数据处理*⼯作顺序:* 1)、线程池创建,准备好core数量的核⼼线程,准备接受任务* 1.1、core满了,就将再进来的任务放⼊阻塞队列中。
空闲的core就会⾃⼰去阻塞队列获取任务执⾏* 1.2、阻塞队列满了,就直接开新线程执⾏,最⼤只能开到max指定的数量* 1.3、max满了就⽤RejectedExecut ionHandler拒绝任务* 1.4、max都执⾏完成,有很多空闲.在指定的时间keepAliveTime以后,释放max-core这些线程new LinkedBlockingDeque<>(): 默认是Integer的最⼤值。
内存不够⼀个线程池core 7; max 20,queue:50,100并发进来怎么分配的;7个会⽴即得到执⾏,50个会进⼊队列,再开13个进⾏执⾏。
剩下的30个就使⽤拒绝策略。
Executors . newCachedThreadPool() core是0,所有都可回收Executors . newF ixedThreadPool()固定⼤⼩,core=max; 都不可回收Executors. newScheduledThreadPool()定时任务的线程池Executors. newSingleThreadExecutor()单线程的线程池,后台从队列⾥⾯获取任务,挨个执⾏import mons.collections.CollectionUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.List;import java.util.concurrent.*;/*** 以下是伪代码,要根据⾃⼰的实际逻辑进⾏整合*/@Servicepublic class PushProcessServiceImpl implements PushProcessService {private final static Logger logger = LoggerFactory.getLogger(PushProcessServiceImpl.class);/***每个线程更新的条数* 这表⽰每次执⾏五千条数据的推送操作*/private static final Integer LIMIT = 5000;/*** 起的线程数*/private static final Integer THREAD_NUM = 5;/*** 创建线程池** - corePoolSize:线程核⼼参数选择了5** - maximumPoolSize:最⼤线程数选择了核⼼线程数2倍数** - keepAliveTime:⾮核⼼闲置线程存活时间直接置为0** - unit:⾮核⼼线程保持存活的时间选择了 TimeUnit.SECONDS 秒** - workQueue:线程池等待队列,使⽤容量初始为100的 LinkedBlockingQueue阻塞队列** 线程池拒绝策略,采⽤了默认AbortPolicy:直接丢弃任务,抛出异常。
SWT中运用多线程编程SWT(Standard Widget Toolkit)是Java的图形用户界面(GUI)工具包,用于创建和管理用户界面的组件。
与AWT(Abstract Window Toolkit)和Swing相比,SWT更接近操作系统的原生界面,因此在性能和可移植性方面具有优势。
SWT中可以使用多线程编程来处理耗时的任务、后台操作以及提高用户界面的响应性。
下面将介绍一些在SWT中使用多线程的技术和最佳实践。
1. 使用工作线程处理耗时任务:当涉及到耗时的任务时,例如网络请求、数据库查询等,最佳做法是将任务放在一个单独的工作线程中执行,以避免阻塞用户界面。
可以使用Java的Thread类或者Executor框架来创建和管理工作线程。
在工作线程完成任务后,使用SWT的异步执行机制(Display.asyncExec)将结果返回到用户界面。
```javaThread thread = new Thread(( ->//执行耗时任务String result = performTimeConsumingTask(;Display.getDefault(.asyncExec(( ->//在用户界面中更新结果label.setText(result);});});thread.start(;```2. 使用后台线程更新用户界面:有时需要在用户界面中更新频繁变化的数据,例如实时监测系统资源使用情况。
在这种情况下,可以使用一个后台线程定时获取数据,并使用SWT的异步执行机制更新用户界面。
确保在用户界面中更新UI元素时使用Display.asyncExec方法,以避免在非UI线程中更新UI,从而避免线程安全问题。
```javaThread thread = new Thread(( ->while (!Thread.interrupted()//获取实时数据ResourceUsage usage = getResourceUsage(;Display.getDefault(.asyncExec(( ->//在用户界面中更新数据progressBar.setSelection(usage.getProgress();label.setText(usage.getLabel();});tryThread.sleep(1000); //等待1秒} catch (InterruptedException e)break;}}});thread.start(;``````java//在用户界面中周期性地更新数据label.setText(getTime();});```4.通过SWT的异步执行机制处理非UI线程的异常:当在工作线程中发生异常时,不能直接在非UI线程中处理异常。
Java⽹络编程(Socket基础,多线程socket,socket中⽂乱码问题)学习笔记1.概念2.简单TCP通信代码,⽤两个java程序模拟客户端和服务器端。
客户端代码:TCP通信的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器回写的数据表⽰客户端的类:.Socket:此类实现客户端套接字(也可以就叫“套接字”)。
套接字是两台机器间通信的端点。
套接字:包含了IP地址和端⼝号的⽹络单位构造⽅法:Socket(String host, int port) 创建⼀个流套接字并将其连接到指定主机上的指定端⼝号。
参数:String host:服务器主机的名称/服务器的IP地址int port:服务器的端⼝号成员⽅法:OutputStream getOutputStream() 返回此套接字的输出流。
InputStream getInputStream() 返回此套接字的输⼊流。
void close() 关闭此套接字。
实现步骤:1.创建⼀个客户端对象Socket,构造⽅法绑定服务器的IP地址和端⼝号2.使⽤Socket对象中的⽅法getOutputStream()获取⽹络字节输出流OutputStream对象3.使⽤⽹络字节输出流OutputStream对象中的⽅法write,给服务器发送数据4.使⽤Socket对象中的⽅法getInputStream()获取⽹络字节输⼊流InputStream对象5.使⽤⽹络字节输⼊流InputStream对象中的⽅法read,读取服务器回写的数据6.释放资源(Socket)注意:1.客户端和服务器端进⾏交互,必须使⽤Socket中提供的⽹络流,不能使⽤⾃⼰创建的流对象2.当我们创建客户端对象Socket的时候,就会去请求服务器和服务器经过3次握⼿建⽴连接通路这时如果服务器没有启动,那么就会抛出异常ConnectException: Connection refused: connect如果服务器已经启动,那么就可以进⾏交互了import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .Socket;import java.util.Scanner;public class TCPClient {public static void main(String[] args) throws IOException {Scanner cin = new Scanner(System.in);Socket socket = new Socket("127.0.0.1",8888);InputStream is = socket.getInputStream();while(true){//给服务器端发数据System.out.println("请输⼊你要向服务器发送的数据:");String sendMessage = cin.nextLine();OutputStream os = socket.getOutputStream();os.write(sendMessage.getBytes());//接收服务器端发过来的数据byte[] getMessage = new byte[1024];int len = is.read(getMessage);String message = new String(getMessage,0,len);System.out.println("收到服务器端发来的数据为: "+message);}}}服务器端代码:TCP通信的服务器端:接收客户端的请求,读取客户端发送的数据,给客户端回写数据表⽰服务器的类:.ServerSocket:此类实现服务器套接字。
科 信l息l科l学 Java与C抖的多线程能力 孟凡涛 f深圳市技工学校,广东深圳518049) 摘要:Java与c静是现扣今网络开发的两大主要平台,而多线程编程则是进行并行处理计算中的基础,本文主要阐述了在Java与c群开发平 台下如何进行多线程编程的方法及注意事项,并且比较和分析两种开发平台下进行多线程编程的差异。 关健词:多线程;并行JtkJ ̄-,Java;c#
前言 线程是允许进行并行计算的—个抽象概念:在 另—个线程完成计算任务的同时,—卟钱程可以对 图像进行更新,第二个线程可以同时处理同—个进 程发出的两 惆络诗I求。从j既念匕讲,线程提供了
—种在—个软件中并行执行代码的方式一每个线 程部 ‘同时’ .1 的内存空间中执行指令,(当 然是缶—个瘦瞪 器匕,这是通过处于运行状态的线 程的交替执 完啵的。),因此,每个线程都可以访问 —个程序内的数据结构。由于这种原因,多线程编 程的难度就可想而知了,因为—个程亭内有许多不 同的线程需要安全地共享数据。 l线程的刨建栅运行 Java在Java long.Thread和Java long Rurmable类中提供了大 糍翔蛩功能。仓!腱—个 线程非常简单 就是扩展Thread类,并调用sty)。 通过创建—个执行Runnable)的类,并将该类作为 参数传递给1t read(),也可以定义—个线程。 下面j盘/ 单咱gJava程序,其中有2个线程 同时在从1数到s,并将结果打印出来。 p.1blje elm 11IrMdil-l 期mple eIl曩Id|ObjeetI pIl蚰c蛐voidmain(s试I.g a神( Md Ⅻds:l1w 11lr d曙 劬emmt=h,ount< ̄length; c0Im越threack[eoun ̄newThread(n Rmmabld ̄ I public void rIl l tllIe曩赳ecttmt]mar ̄ l } imblic SuIlic void o0un嵋( 1 int o0IIn ommt<=5;ooIlIIe System out print(count l l 可以使用System Threading Thread和sys— tern. Threadin ̄ThreadStart=个类将上述的Java 程序转换为c#语膏 IlB.mgSystem.Threading; public class Threadin ̄xtmapb.Objeet{ public matic void MaiI 11l d reads=new nl a皤 f0审Il count=heotmt<=threadR g血 eoIln¨ £hr酗d《∞un n w Thre ̄f new l"hreadSma 曲臻 threadsI∞un司Sta l l public static void Cotm ̄ int eo ̄t=-l;eotmt<=5;count) Console Write(c ̄aunt”’’ l J 这个例子中有一些小技巧。Java允许扩展 iav&lan Thread类和执行Java lang Runnable 接口,c#则没有为我们提供这些便利。—个c#中 的Thread对象是不可知的,必须通过ThreadStart 进行创建,这意味着不能使用内部的类模式,而必 须创建—个对象,而目必须传递给线程—个对象的 方法供线程执行用。 2线程的使用 Java中存在许多编程^员希望能够对线程使 用的标准操作例如,测试线程是否存在、加人—个 线程直到它死亡 死卜卟唠强等。 线程管理的函数 Java中iavalang Thread中的方法和c样中 System Threading Thread对象的对比。 setDaemon(boolean 0 IsBackground设置属性值 使— 的进回妫—个新线程瘦口果 的所有进程都成了新线程,程序将停止运行]。 isDaem 疗法 IsBaekground获取属性 如果该线程是—个后台线程,则返回真值。 isAlivd 去 IsAlive获取属性 则返回真值。 InterruptO ̄ 尽管在Java中这—方法可以用来设置线程的 中断状态,而且可以用来检查线程是否被中断。在 C#中没有相应的方法,对—个没有处于阻塞状态 的线程执行Interrupt方法将使下一次阻塞调用自 动失效。 isIntem pte 法 n/a 则返回真值。 sleelX!ong milli ̄)和sleep ̄ong millis,intnanos) Sleep(int miUiseeond Timeeut)and Sleep  ̄System Timesp 段给定的时间,或直 到它被中断。这—方法将在Java中将产生—个i— va lang.InterruptedException状态,在c#中将产 生Syslem-Threadin ̄ThteadlnterruptedException 状态。 Join(),join ong millis)和join O0ng miRi ̄,int- nanos)方法与Java中汉依出删设定不同的是,在 c#语言中则依据线程停止运行是由于线程死白返 回真 提超时(返回佃而返回——t 布尔型变量。 suspend叻、法 二者的功能相同。这—方法容易引起死循环, 如果一个 有系统关健资源自§线程被挂起来,则在 这—线程恢复运行之前,其他的线程不能访问该资 源。 resume1方、法 恢复—个被挂起的线程。 St0p0 法 Ab0I 法 参见下面的‘线程停止’ 彩 3线程的中止 由于能够在没有任何征兆的情况下使运行的 程序进人一种混乱的状态,Java中的Thread.stop 受到了普遍的反对。根据所调用的stop) ̄,—个 未经检查的Java laI1 ThreadDeath错误将会破坏 正在运行着的程序的栈,随着它的不断运行,能够 解除任何被锁定的对象。由于这些锁被不分青红皂 白地被打开,由它们所保护的数据就非常可能陷人 混乱状态中。根据当前的Java文挡,推荐的中止一
JAVA多线程编程技术 第1章 基础和使用 1.1 多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念。 进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 什么是多线程呢?即就是一个程序中有多个线程在同时执行。 通过下图来区别单线程程序与多线程程序的不同: 单线程程序:即,若有多个任务只能依次执行。当上一个任务执行结束后,下一个任务开始执行。如,去网吧上网,网吧只能让一个人上网,当这个人下机后,下一个人才能上网。 多线程程序:即,若有多个任务可以同时执行。如,去网吧上网,网吧能够让多个人同时上网。
1.2 程序运行原理
分时调度 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。 抢占式调度 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
1.2.1 抢占式调度详解 大部分操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个程序。比如:现在我们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。此时,这些程序是在同时运行,”感觉这些软件好像在同一时刻运行着“。 实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。 其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。 1.3 主线程 回想我们以前学习中写过的代码,当我们在dos命令行中输入java空格类名回车后,启动JVM,并且加载对应的class文件。虚拟机并会从main方法开始执行我们的程序代码,一直把main方法的代码执行结束。如果在执行过程遇到循环时间比较长的代码,那么在循环之后的其他代码是不会被马上执行的。如下代码演示: class Demo{ String name; Demo(String name){ this.name = name; } void show() { for (int i=1;i<=10000 ;i++ ) { System.out.println("name="+name+",i="+i); } } }
class ThreadDemo { public static void main(String[] args) { Demo d = new Demo("小强"); Demo d2 = new Demo("旺财"); d.show(); d2.show(); System.out.println("Hello World!"); } }
若在上述代码中show方法中的循环执行次数很多,这时在d.show();下面的代码是不会马上执行的,并且在dos窗口会看到不停的输出name=小强,i=值,这样的语句。为什么会这样呢? 原因是:jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。当程序的主线程执行时,如果遇到了循环而导致程序在指定位置停留时间过长,则无法马上执行下面的程序,需要等待循环结束后能够执行。 那么,能否实现一个主线程负责执行其中一个循环,再由另一个线程负责其他代码的执行,最终实现多部分代码同时执行的效果? 能够实现同时执行,通过Java中的多线程技术来解决该问题。
1.4 Thread类
该如何创建线程呢?通过API中搜索,查到Thread类。通过阅读Thread类中的描述。Thread是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。 构造方法 常用方法
继续阅读,发现创建新执行线程有两种方法。 一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。创建对象,开启线程。run方法相当于其他线程的main方法。 另一种方法是声明一个实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。
1.5 创建线程方式一:继承Thread类
创建线程的步骤: 1 定义一个类继承Thread。 2 重写run方法。 3 创建子类对象,就是创建线程对象。 4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。 测试类 public class Demo01 { public static void main(String[] args) { //创建自定义线程对象 MyThread mt = new MyThread("新的线程!"); //开启新线程 mt.start(); //在主方法中执行for循环 for (int i = 0; i < 10; i++) { System.out.println("main线程!"+i); } } } 自定义线程类 public class MyThread extends Thread { //定义指定线程名称的构造方法 public MyThread(String name) { //调用父类的String参数的构造方法,指定线程的名称 super(name); } /** * 重写run方法,完成该线程执行的逻辑 */ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(getName()+":正在执行!"+i); } } }
思考:线程对象调用 run方法和调用start方法区别? 线程对象调用run方法不开启线程。仅是对象调用方法。线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行。
1.5.1 继承Thread类原理 我们为什么要继承Thread类,并调用其的start方法才能开启线程呢? 继承Thread类:因为Thread类用来描述线程,具备线程应该有功能。那为什么不直接创建Thread类的对象呢?如下代码: Thread t1 = new Thread(); t1.start();//这样做没有错,但是该start调用的是Thread类中的run方法,而这个run方法没有做什么事情,更重要的是这个run方法中并没有定义我们需要让线程执行的代码。
创建线程的目的是什么? 是为了建立程序单独的执行路径,让多部分代码实现同时执行。也就是说线程创建并执行需要给定线程要执行的任务。 对于之前所讲的主线程,它的任务定义在main函数中。自定义线程需要执行的任务都定义在run方法中。 Thread类run方法中的任务并不是我们所需要的,只有重写这个run方法。既然Thread类已经定义了线程任务的编写位置(run方法),那么只要在编写位置(run方法)中定义任务代码即可。所以进行了重写run方法动作。
1.5.2 多线程的内存图解 多线程执行时,到底在内存中是如何运行的呢? 以上个程序为例,进行图解说明: 多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。
当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。
1.5.3 获取线程名称 开启的线程都会有自己的独立运行栈内存,那么这些运行的线程的名字是什么呢?该如何获取呢?既然是线程的名字,按照面向对象的特点,是哪个对象的属性和谁的功能,那么我们就去找那个对象就可以了。查阅Thread类的API文档发现有个方法是获取当前正在运行的线程对象。还有个方法是获取当前线程对象的名称。既然找到了,我们就可以试试。 Thread.currentThread()获取当前线程对象 Thread.currentThread().getName();获取当前线程对象的名称 class MyThread extends Thread { //继承Thread MyThread(String name){ super(name); } //复写其中的run方法 public void run(){ for (int i=1;i<=20 ;i++ ){ System.out.println(Thread.currentThread().getName()+",i="+i); } } } class ThreadDemo { public static void main(String[] args) { //创建两个线程任务 MyThread d = new MyThread(); MyThread d2 = new MyThread(); d.run();//没有开启新线程, 在主线程调用run方法 d2.start();//开启一个新线程,新线程调用run方法 } }
通过结果观察,原来主线程的名称:main;自定义的线程:Thread-0,线程多个时,数字顺延。如Thread-1...... 进行多线程编程时,不要忘记了Java程序运行是从主线程开始,main方法就是主线程的线程执行内容。
1.6 创建线程方式—实现Runnable接口
创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。 为何要实现Runnable接口,Runable是啥玩意呢?继续API搜索。 查看Runnable接口说明文档:Runnable接口用来指定每个线程要执行的任务。包含了一个 run 的无参数抽象方法,需要由接口实现类重写该方法。