java多线程编程核心技术——第一章总结
目录:
- 1.1进程、多线程的概念,及线程的优点
- 1.2多线程的使用
- 1.3currentThread()方法
- 1.4isAlive()方法
- 1.5sleep()方法
- 1.6getId()方法
- 1.7停止线程
- 1.8暂停线程
- 1.9yield()方法
- 1.10线程的优先级
- 1.11守护线程
1.1进程、多线程的概念及线程的优点
进程的概念:
百度百科讲解:
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。
程序是指令、数据及其组织形式的描述,进程是程序的实体。 着重点的话,就是最后一句进程是程序的实体,个人理解的话,也可以认为是进程就是程序的表现,你所看到的每一个进程,其实质都是一个程序,或者说是在运行的程序。
线程的概念:
线程可以理解成在进程中独立运行的子任务,如在qq运行中,好友视频线程,文件下载线程,传输数据线程等,这些不同的独立的任务都在同时的进行,其中每一项任务都可以理解成是"线程"在工作。
线程就是子任务。
1.2多线程的使用
想要实现线程,有两种方式(目前):
- 继承Thread类
- 实现Runnable接口
注:Thread类也实现了Runnable接口。
若想实现“多继承”只能通过实现Runnable接口来实现。继承Thread类与实现Runnable接口,创建的线程工作时的性质都是一样的。
通过重写run()方法,将需要线程开启后执行的任务放入其中就可以通过调用线程对象的start()或者run()方法来实现开启线程。
注:start()方法与run()方法的区别:
start()方法是另外开启一个线程来执行run()里面的内容,run()方法则是当前线程获取run()里面的执行权。一个是开启新的线程执行任务,一个是当前线程执行任务。
书中的话是:Thread.start()方法是告诉“线程规划器”此线程已经准备就绪,等待调用线程对象的run()方法,这个过程就是让系统安排一个时间来调用Thread中的run()方法。从而使线程运行,启动线程,具有异步的效果。
线程的调用具有随机性,因为多线程的实现是在极短的时间内cpu在不同线程间跳动来实现的(对于线程来说就是获取了执行权)。因为执行权的获取、失去都具有随机性,所以导致了线程的调用也具有随机性。
Thread的构造方法:
由于Thread类实现了Runnable接口。所以构造方法中Thread(Runnable targer)不仅可以传入Runnable接口对象,还可以传入Thread对象(java三大特性:多态),这样可以将当前线程的任务交由其他线程来执行。
线程的安全性问题:
当多线程操作共享数据时,如果不进行处理(加锁),就会出现数据不同步的现象,也就是说所谓的线程不安全问题。
synchronized关键字解决线程不安全问题:可以在线程的run()上加上关键字synchronized来为线程加锁,当第一个线程执行到此处时,会进行加锁处理,在其运行完之前不会放开锁,此时其他线程要想获得执行权,只能排队等到当前线程运行完run()代码(放开锁)后才能获得线程执行权并重新加锁。
注:synchronized关键字可以在任意对象和方法上加锁,而这种加锁的代码称为:“互斥区”或“临界区”。
注:非线程安全:多个线程对同一个对象中的同一个实例变量进行操作时出现值被更改、值不同步的情况,进而影响程序的执行流程。
i--与System.out.println()的异常:
println()源码:
若自增自减操作是在println()操作外进行的,那么就有可能会出现非线程安全问题。
注:
在某些JVM中,i--的操作要经历下面三个步骤:
- 取得原有i值
- 计算i-1
- 对i进行赋值
若上述任何一步中,有多个线程同时访问,那么就可能会出现多线程问题。
1.3CurrentThread()方法
currentThread()方法可以返回正在执行的线程的调用信息。
注:
Thread.currentThread()获得的始终是执行start()方法的线程(或者说当前运行的线程)。
而this获得的都是run()方法所在线程对象的名称。
Thread.currentThread().getName()和this.getName()方法都可以获取线程的名字。
1.4isAlive()方法
方法isAlive()是判断当前线程是否处于活动状态。
活跃状态:线程已经启动且尚未终止。线程处于正在运行或准备开始运行的状态,就认为线程是“存活的”。
1.5sleep()方法
方法sleep()的作用是在指定的毫秒数内让当前"正在执行的线程"休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。
1.6getId()方法
getId()方法的作用是获取线程的唯一标识。
1.7停止线程
线程停止:在线程处理完任务之前,停掉正在做的操作,也就是放弃当前操作。
在java中有三种方法可以实现线程的停止:
- 使用退出标志,使线程正常退出,也就是当run方法执行完后线程终止。
- 使用stop()强行终止线程。但是不推荐这个方法,因为stop()与suspend()以及resume()一样,都是作废过期的方法,使它们产生不可预期的结果。
- 使用interrupt()方法中断线程。该方法不会终止一个线程,还需要加入一个判断才能够完成线程的终止。
停不了的线程:
使用interrupt()方法停止线程,但是interrupt()方法并不像循环中的break关键字一样可以立即起效,interrupt()方法仅仅是在当前线程中打了一个停止的标记,并没有真正停止线程。
判断线程是否停止:
在Java的SDK中,Thread.java类里提供了两种方法判断线程是否停止
根据JDK来看interrupted()方法会清除停止状态,也就是说当前如果出现暂停,若调用多次后第二次之后一定返回false。
isInterrupted()方法不会清除停止状态。
2017/12/15补充:
interrupt()仅仅是为当前线程添加一个状态,并不影响线程的执行。
即,线程此时的状态为打断状态,但是线程是正常执行run()里面的内容的。
若想实现真正的打断,可以通过interrupted()或者isInterrupted()与判断语句实现打断。
能停止的线程——异常法:
在线程执行的run()中直接抛出一个异常就可以将当前在运行的线程停止。
在沉睡中停止:
若某一线程处于sleep状态,此时将该线程停止的话就会抛出异常java.lang.InterruptedException:sleep interrupted进而停止线程。
注:若先进入interrupt中,在进行睡眠还是会爆出该异常。
2017/12/15补充:
注:实际上是,只要线程在进入睡眠状态时,打断状态是true,就会报出异常。
能停止的线程——暴力停止:
stop()方法停止线程是暴力的,该方法会直接停止线程。
方法stop()与java.lang.ThreadDead异常:
调用stop()方法时,会抛出java.lang.ThreadDeath异常,但在通常情况下,此异常不需要显示地捕捉。
注:如果不特地注明ThreadDeath方法时,是不会爆出异常进入catch中的。
stop()方法已经作废,因为如果强制停止线程会导致一些清理的工作无法完成,另外一种情况就是对锁定的对象进行了“解锁”,导致数据得不到同步的处理,出现数据不一致的问题。
注:stop()方法会杀死线程,然后将锁释放,此时若run()中的共享数据修改没有完成,可能会出现数据不同步的现象。
使用return()停止线程:
可以结合interrupt()与判断线程是否停止的两个方法,通过判断实现是否通过return()停止线程。
注:仅仅使用return;即可。return;可以结束方法的执行。
1.8暂停线程
suspend()与resume()的使用:
在java中,使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
suspend()与resume()的缺点——独占:
在使用suspend与resume方法时,可能会导致公共的同步对象的独占发生,使得其他线程无法访问公共同步对象。
即若在临界区(互斥区)中停止了线程,那么其他线程在resume()前将永远无法获得锁。
注:println()方法内部使用了synchronized关键字,这可能导致在一些测试中出现异常。
suspend()与resume()的缺点——不同步:
若方法使用不当,可能会导致出现数据更新的不同步现象。
1.9yield方法
yield()方法的解释:放弃当前cpu资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不能确定,有可能刚刚放弃,但马上又获得CPU时间片。
1.10线程的优先级
在操作系统中,线程是有优先级划分的,优先级较高的线程会得到相对较多的资源。也就是说CPU会优先执行优先级较高的线程对象中的任务。
设置线程优先级有助于帮“线程规划器”确定下次选择哪一个线程来优先执行。
设置线程的优先级使用setPriority()方法,此方法在JDK的源代码如下:
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
在java中,线程的优先级分为1~10这10个优先级,如果小于1或者大于10,则JDK抛出异常IllegalArgumentException()。
JDK常用下面三个量来预置定义优先级的值。
线程优先级的继承特性:
在java中线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A是一样的。
优先级具有规则性:
线程的执行顺序与线程代码的执行顺序无关,与线程的优先级有关,优先级越高越先执行。
优先级具有随机性:
随机性意味着优先级高的线程不一定总是能优先执行完。
优先级越高的线程执行速度越快。
1.11守护线程
在Java中有两种线程,一种为用户线程,一种为守护线程。
守护线程是一种特殊的线程,它具有“陪伴”的含义,当进程中不存在非守护线程时,则守护线程自动销毁。
典型的守护线程就是垃圾回收线程。
当进程中没有线程了,则垃圾回收线程也就没有存在的必要了,自动销毁。
任何一个守护线程,都是JVM中所有的非守护线程的保姆,只要当前JVM实例中存在任何一个非守护线程,且没有结束,守护线程就在工作,只有当最后一个非守护线程结束时,守护线程才随着JVM一同结束工作。
通过setDaemon(Boolean)方法来设置守护线程。
注:该方法一定要在start()方法前调用,不然会抛出异常。
本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。
java多线程编程核心技术——第一章总结的更多相关文章
- java多线程编程核心技术——第二章
第一节synchronized同步方法目录 1.1方法内的变量为线程安全的 1.2实例变量非线程安全 1.3多个对象多个锁 1.4synchronized方法与锁对象 1.5脏读 1.6synchro ...
- java多线程编程核心技术——第二章总结
第一节synchronized同步方法目录 1.1方法内的变量为线程安全的 1.2实例变量非线程安全 1.3多个对象多个锁 1.4synchronized方法与锁对象 1.5脏读 1.6synchro ...
- Java多线程编程核心技术
Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...
- 《Java多线程编程核心技术》推荐
写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...
- Java多线程编程核心技术(三)多线程通信
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...
- 《java多线程编程核心技术》(一)使用多线程
了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...
- 《java多线程编程核心技术》不使用等待通知机制 实现线程间通信的 疑问分析
不使用等待通知机制 实现线程间通信的 疑问分析 2018年04月03日 17:15:08 ayf 阅读数:33 编辑 <java多线程编程核心技术>一书第三章开头,有如下案例: ...
- 《Java多线程编程核心技术》知识梳理
<Java多线程编程核心技术> @author ergwang https://www.cnblogs.com/ergwang/ 文章末尾附pdf和png下载链接 第1章 Java多线程技 ...
- Java多线程编程核心技术---学习分享
继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...
随机推荐
- Spring @Configuration注解
1 该注解的用途 这个注解表示这个类可以作为spring ioc容器bean的来源,其本质上它是对xml文件中创建bean的一种替换.有了这个注释,Spring framework就能在需要的时候构造 ...
- ALV 表头 ADD_TEXT
[转自http://lz357502668.blog.163.com/blog/static/16496743201252891452493/] CALL METHOD valid_reference ...
- linux 9 -- 交互式使用Bash Shell
二十二. 交互式使用Bash Shell: 1. 用set命令设置bash的选项: 下面为set主要选项的列表及其表述: 选项名 开关缩写 描述 allexport -a 打开此开关 ...
- 有关java之反射的使用
1 public class Demo02 { 2 @SuppressWarnings("all") 3 public static void main(String[] args ...
- rails 命名
1.model rails g model wordSetting model:WordSetting has_many: word_settings table: word_settings vie ...
- 高性能javascript学习总结(1)--加载与运行
一.脚本的位置 我们知道,一个<script>标签可以放在 HTML 文档的<head>或<body>标签中,但是浏览器是怎么加载和执行这些java ...
- ubuntu14.04 python2.7安装MySQLdb
安装依赖: sudo apt-get install libmysqlclient-dev libmysqld-dev python-dev python-setuptools 安装MySQLdb p ...
- opencv学习之路【四】——opencv文件结构介绍
这里要感谢这篇博主的文章 部分内容转载自此 opencv在2.3版本之前 都是用的c语言实现的 而在2.3以后的版本 做了很多重大的改变 其中最主要的是用c++重写大部分结构 然后文件的结构和2.0之 ...
- <开源项目分析>Cisco的开源视频加解码器THOR(H.264解码)
原创博客,转载请联系博主! 题外话:自学了快两个月的Perl语言,本来打算写两篇基础介绍的博文来科普一下一些小技巧,但是仔细想想还是没有必要了吧,毕竟现在无论是在用Perl5还是Perl6的人都是小众 ...
- codeforces 686B
题意:给出一个序列,只允许进行相邻的两两交换,给出使序列变为非降序列的操作方案. 思路:关键点是操作次数不限,冒泡排序. #include<iostream> #include<cs ...