Java 并发编程实战:如何创建并运行java线程
yuyutoo 2024-10-12 01:03 5 浏览 0 评论
在计算机世界中,并发是指一系列相互无关的任务在一台计算机上同时运行。对于有多个处理器或者多核处理器的计算机来说,这个同时性是真实发生的。然而,对于只有单核处理器的计算机来说,它仅仅是表面现象。
所有现代操作系统均支持并发地执行任务。用户可以在听音乐或者浏览网页的同时阅读邮件。这种并发是进程级别的并发。在同一进程内,也可以有多种同时运行的子任务,我们将这些并发的子任务称为线程。与并发性有关的另一个概念是并行性( parallelism )。虽然它与并发性的概念不同,但是有一定联系。一些学者认为,当多线程应用程序运行在单核处理器上时,程序就是并发运行的;当多线程应用程序运行在多个处理器或者多核处理器上时,程序就是并行运行的。还有一些学者认为,多线程应用程序的线程执行顺序若不是预先定义的,程序就是并发运行的;如果多线程应用程序的线程按照指定顺序执行,那么这个程序就是并行运行的。
本章介绍了如何使用Java 9 API来进行基本的线程操作,包括创建和运行线程、处理线程内抛出的异常、将线程分组,并将分组作为一个整体处理组内的线程。
1.2线程的创建、运行和设置
本节介绍如何使用Java APl对线程进行基本的操作。与Java语言中的基本元素一样,线程也是对象(Object )。在Java中,创建线程的方法有以下两种。
直接继承Thread类,然后重写run()方法。
构建一个实现Runnable接口的类并重写run()方法,然后创建该类的实例对象,并以其作为构造
参数去创建Thread类的对象。建议首选这种方法,因为它可以带来更多的扩展性。
在本节中,我们将采用第二种方法创建线程,然后学习如何改变线程的属性。Thread类包含如下一些信息属性,它们能够辅助区分不同的线程、反映线程状态、控制其优先级等。
ID:该属性存储了每个线程的唯一标识符。
Name :该属性存储了线程的名字。
Priority:该属性存储了 Thread对象的优先级。在Java 9中,线程优先级的范围为1-10 ,其中1表示最低优先级, 10表示最高优先级。通常不建议修改线程的优先级。线程优先级仅供底层操作系统作为参考,不能保证任何事情,如果一定要修改,请知晓优先级仅仅代表了一种可能性。
Status :该属性保存了线程的状态。在Java中,线程有6种状态-Thread.State枚举中定义这些状态: NEW、 RUNABLE 、 BLOCKED 、wAITING、TIMED_MAIING和TERMINATED 。这些状态的具体意义如下。
NEW: 线程已经创建完毕但未开始执行。
RUNNABLE: 线程正在JVM中执行。
BLOCKED: 线程处于阻塞状态,并且等待获取监视器。
WAITING: 线程在等待另一个线程。
TIMED-MAITING: 线程等待另一个线程一定的时间。
TERMTNATED: 线程执行完毕。
本节将在一个案例中创建10个线程来找出20000以内的奇数。
项目准备
本案例是用Eclipse IDE实现的。如果开发者使用Eclipse或者其他IDE (例如NetBeans ) ,则应打开它并创建一个新的Java项目。
案例实现
根据如下步骤实现本案例
1,创建一个名为calculator的类,并实现Runnable接口:
Public class Calculator implements Runnable{
2,实现run()方法。在这个方法中,存放着线程将要运行的指令。在这里,这个方法用来计算20000以内的奇数
@Override
public void run()
long current =1L;
long max =20000L;
long numPrimes = OL;
System.out.printf("Thread '%s': START\n"
Thread.currentThread().getName());
while (current <=max)
if (isPrime(current)){
numPrimes++;
}
current++;
}
System.out.printf("Thread '%s'; END. Number of Primes: %d\n"
Thread.currentThread() .getName(), numPrimes);
}
3.实现辅助方法isprime() 。该方法用于判断一个数是否为奇数:
private boolean isPrime (long number) {
if (number <=2){
return true;
}
for (long i =2; i<inumber; i++){
if ((number % i) ==0){
return false;
}
return true;
}
}
4,实现应用程序的主方法,创建包含main()方法的Main类:
public class Main {
public static void main(String[] args) {
5,首先,输出线程的最大值、最小值和默认优先级:
System.out.printf("minimum Priority: %s\n",
Thread.MIN_PRIORITY);
System.out, printf{"Normal Priority: %s\n",
Thread. NORM_PRIORITY);
System.out.printf("Maximun Priority: %s\n",
Thread.MAX_PRIORITY);
6,创建10个 Thread对象,分别用来执行10个 calculator 任务。再创建两个数组,用来保存
Thread 对象及其State 对象。后续我们将用这些信息来查看线程的状态。这里将5个线程设置为最大优先级,另5个线程设置为最小优先级:
Thread threads [];
Thread,state status[];
threads = new Threadr10];
status = new Thread.Stater[10];
for (int i = 0; i < 10; i++){
threads[i] = new Thread (new Calculator());
ir ((i% 2) ==0) {
threads [i].setPriority(Thread.MAX_PRIORITY);
}else{
threads[i].setpriority(Thread.MIN_PRIORITY));
}
threads[i].setName("My Thread"+i);
}
7,接着将一些必要的信息保存到文件中,因此需要创建try-with-resources语句来管理文件。在这个代码块中,先将线程启动前的状态写入文件,然后启动线程:
try (Filewriter file = new Filewriter(".\\data\\log.txt");
Printwriter pw = new Printwriter(file);){
for (int i =0; i <10; i|++){
pw.println("Main : Status of Thread "+i+":"+
threads[i].getstate());
status[i] = threads[i].getstate();
}
for (int i =0; i < 10; i++){
threads[i].start();
}
8,等待线程运行结束。在1.6节中,我们将用join()方法来等待线程结束。本案例中,由于我们需要记录线程运行过程中状态的转变,因此不能使用join()方法来等待线程结束,而应使用如下代码:
boolean finish = false:
while (!finish){
for (int i =0; i<10; i++){
if (threads[i].getstate() != status[i]) {
writeThreadInfo(pw, threads[i], status [i]);
status[i] = threads[i].getstate();
}
}
finish =true;
for (int i =0; i<10; i++) {
finish =finish && (threads[i].getstate() ==
State. TERMINATED);
}
}
}catch (IOException e){
e.printstackTrace();
}
}
9,在上述代码中,我们通过调用writeThreadInfo()方法来将线程信息记录到文件中。代码如下:
private static void writeThreadInfo(PrintWriter pw,
Thread thread,
state state) {
pw.printf("Main: Id %d -%s\n", thread.getId(),
thread.getName());
pw.printf("Main: priority:%d\n", thread.getPriority());
pw.printf ("Main: Old state: %s\n", state);
pw.printf ("Main: New State: %s\n", thread.getstate());
pw.printf("Main :***********************************************\n");
}
10,运行程序,然后观察不同的线程是如何同时运行的。
结果分析
下图是程序在控制台的输出,从中可以看到,线程正在并行处理各自的工作。
从下面的屏幕截图中可以看到线程是如何创建的,拥有高优先级的偶数编号线程比低级优先级的奇数编号线程优先执行。该截图来自记录线程状态的log.tet文件。
每个Java应用程序都至少有一个执行线程。在程序启动时, JVM会自动创建执行线程运行程序的main()方法
当调用Thread 对象的start()方法时,JVM才会创建一个执行线程。也就是说,每个Thread对象的start()方法被调用时,才会创建开始执行的线程。
Thread类的属性存储了线程所有的信息。操作系统调度执行器根据线程的优先级,在某个时刻选择一个线程使用CPU ,并且根据线程的具体情况来实现线程的状态。
如果没有指定线程的名字,那么JVM会自动按照Thread -xx格式为线程命名,其中xx是一个数字。线程的ID和状态是不可修改的,事实上, Thread类也没有实现setIa()和setstatus()方法,因为它们会引入对ID和状态的修改。
一个Java程序将在所有线程完成后结束。初始线程(执行main()方法的线程)完成,其他线程仍会继续执行直到完成。如果一个程调用system.exit()命令去结束程序,那么所有线程将会止各自的运行。
创建一个Thread对象并不意味着会创建一个新的执行线程。同样,调用实现Runnable接口类的run()方法也不会创建新的执行线程。只有调用了start()方法,一个新的执行线程才会真正创建。
其他说明
正如本节开头所说,还有另一种创建执行线程的方法——实现一个继承Thread的类,并重写其
run()方法,创建该类的对象后,调用start()方法即可创建执行线程。
可以使用Thread类的静态方法 currentThread()来获取当前运行线程的Thread对象。
调用setpriority()方法时,需要对其抛出的IllegalArgumentException 异常进行处理,以防传入的优先级不在合法范围内(1和10之间)。
本文节选自《Java 9 并发编程实战》
本书将带你了解所有的新API,向您展示如何构建并行多线程应用程序。这本书涵盖了所有Java并发API的元素,包括基本配方,这些帮助您利用激动人心的新功能。您将学习如何使用并行和反应流来处理大规模数据集。接下来,您将继续创建流,并使用他们所有中间和终端的操作以一种并行且函数性的方式来进行数据的收集。此外,你会了解一系列的实战方式,如线程管理、同步、执行人、并行和反应流等。
相关推荐
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
-
Mysql和Oracle实现序列自增/*ORACLE设置自增序列oracle本身不支持如mysql的AUTO_INCREMENT自增方式,我们可以用序列加触发器的形式实现,假如有一个表T_WORKM...
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
-
概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...
- MySQL CREATE TABLE 简单设计模板交流
-
推荐用MySQL8.0(2018/4/19发布,开发者说同比5.7快2倍)或同类型以上版本....
- mysql学习9:创建数据库(mysql5.5创建数据库)
-
前言:我也是在学习过程中,不对的地方请谅解showdatabases;#查看数据库表createdatabasename...
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
-
执行"CREATETABLE新表ASSELECT*FROM原表;"后,新表与原表的字段一致,但主键、索引不会复制到新表,会把原表的表记录复制到新表。...
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
-
在街上看到的PandaDunk的超载可能让一些球鞋迷们望而却步,但Dunk的浪潮仍然强劲,看不到尽头。我们看到的很多版本都是为女性和儿童制作的,这种新配色为后者引入了一种令人耳目一新的新选择,而...
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
-
多功能雷达AN/SPY-1的特性和技术能力,该雷达已经在美国海军服役了30多年,其修改-AN/SPY-1A、AN/SPY-1B(V)、AN/SPY-1D、AN/SPY-1D(V),以及雷神...
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
-
全面分析汽车音响使用或安装技术常识一:主机是大多数人最熟习的音响器材,有关主机的各种性能及规格,也是耳熟能详的事,以下是一些在使用或安装时,比较需要注意的事项:LOUDNESS:几年前的主机,此按...
- 【推荐】ProAc Response系列扬声器逐个看
-
有考牌(公认好声音)扬声器之称ProAcTablette小音箱,相信不少音响发烧友都曾经,或者现在依然持有,正当大家逐渐掌握Tablette的摆位设定与器材配搭之后,下一步就会考虑升级至表现更全...
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
-
作者:初吻给了烟sco混迹张大妈时日不短了,手没少剁。家里有了汪星人,吸尘器使用频率相当高,偶尔零星打扫用卧式的实在麻烦(汪星人:你这分明是找借口,我掉毛是满屋子都有,铲屎君都是用卧式满屋子吸的,你...
- 专题|一个品牌一件产品(英国篇)之Quested(罗杰之声)
-
Quested(罗杰之声)代表产品:Q212FS品牌介绍Quested(罗杰之声)是录音监听领域的传奇品牌,由英国录音师RogerQuested于1985年创立。在成立Quested之前,Roger...
- 常用半导体中英对照表(建议收藏)(半导体英文术语)
-
作为一个源自国外的技术,半导体产业涉及许多英文术语。加之从业者很多都有海外经历或习惯于用英文表达相关技术和工艺节点,这就导致许多英文术语翻译成中文后,仍有不少人照应不上或不知如何翻译。为此,我们整理了...
- Fyne Audio F502SP 2.5音路低音反射式落地音箱评测
-
FyneAudio的F500系列,有新成员了!不过,新成员不是新的款式,却是根据原有款式提出特别版。特别版产品在原有型号后标注了SP字样,意思是SpecialProduction。Fyne一共推出...
- 有哪些免费的内存数据库(In-Memory Database)
-
以下是一些常见的免费的内存数据库:1.Redis:Redis是一个开源的内存数据库,它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis提供了快速的读写操作,并且支持持久化数据到磁...
- RazorSQL Mac版(SQL数据库查询工具)
-
RazorSQLMac特别版是一款看似简单实则功能非常出色的SQL数据库查询、编辑、浏览和管理工具。RazorSQLformac特别版可以帮你管理多个数据库,支持主流的30多种数据库,包括Ca...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
- MySQL CREATE TABLE 简单设计模板交流
- mysql学习9:创建数据库(mysql5.5创建数据库)
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
- 【推荐】ProAc Response系列扬声器逐个看
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)