java厨房_Java多线程基础
目录:
进程和线程
为什么使用多线程?
多线程的创建方式
Runnable与Thread两种方式比较
start()与run()方法
线程的生命周期/状态转换
常用方法使用与解读
线程的优先级
守护线程
1、进程和线程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
一个程序就是一个进程,而一个程序中的多个任务则被称为线程。
进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位。
2、为什么要使用多线程?
提升效率,提升性能;发挥多核CPU的优势。
防止阻塞:从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。
3、多线程的创建方式[细分为5种]
继承Thread类,重写run方法。new一个实例。
实现Runnable接口,重写run方法。作为参数传入Thread thread = new Thread(参数);来创建。
匿名内部类的方式(与实现Runnable接口一样,只是形式不同 )
通过并发包中Callable、Callback来创建
通过线程池来创建线程
4、Runnable与Thread两种方式比较
继承Thread不必多说,继承后重写run方法。new一个实例调用start()方法就可以了。
两者非要比较的话,使用Runnable较好,因为实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度,面向接口编程也是设计模式6大原则的核心。
这里重点看下实现Runnable接口创建线程,实现Runnable接口实际上还是需要Thread类来创建线程,我们来看下Thread的构造方法API:
另外需要说明的是Thread.java类也实现了Runnable接口,如下图:
那也就意味着Thread的构造函数不仅可以传入Runnable接口的对象还可以传入一个Thread类的对象,这样就可以将一个Thread类的run()方法交由其他线程来调用。
5、start()与run()方法
只有调用了start()方法,才会表现出多线程的特性,不同线程的run()方法里面的代码交替执行。如果只是调用run()方法,那么代码还是同步执行的,必须等待一个线程的run()方法里面的代码全部执行完毕之后,另外一个线程才可以执行其run()方法里面的代码。
6、线程的生命周期/状态转换
生命周期的五种状态【简单版文字描述】:
新建(new Thread)当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread t1=new Thread();
就绪(runnable)线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
运行(running)线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
自然终止:正常运行run()方法后终止
异常终止:调用stop()方法让一个线程终止运行,这里说明下stop()方法虽然可以停止线程,但这个方法线程不安全,在新版本的java中已经被废弃。
堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用notify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)废弃
更全的线程状态转换图如下:
7、常用方法使用与解读
start():使线程进入“就绪”(可运行)状态,通知jvm开启新线程来执行run方法。如果多次调用了start()方法,则会出现Exception in thread "main" java.lang.IllegalThreadStateException因为start会修改当前线程的状态变量,只有状态变量是初始值时才能start。
线程中断相关:
stop()【废弃】:停止一个线程,可以使用Thread.stop()方法,但是他是不安全的,而且已经被废弃了呢。调用的时候还会抛出一个java.lang.ThreadDeath异常 ,但是通常情况下,此异常不需要显示的捕捉。废弃原因:因为强制让线程停止则有可能使一些请理性的工作得不到完成。另外情况就是对锁定的对象进行了“解锁”,导致 数据得不到同步的处理,出现数据不一致的问题。
interrupt():大多数停止一个线程的操作是使用Thread.interrupt()方法,尽管名义为“中止,停止”但这个方法不会终止一个正在运行的线程,只是打了一个标记,还需要加入一个判断才可以完成线程的停止。Thread.java中提供了两个方法:
this.interrupted():测试当前线程是否已经中断。public static boolean interrupted()
this.isInterrupted():测试线程是否已经中断。public boolean isInterrupted()
具体终止线程操作(来源网络):https://www.cnblogs.com/jenkov/p/juc_interrupt.html
其中的return停止线程可以的,但是还是建议使用“抛异常”的方法来实现线程的停止,因为在catch块中还可以将异常上抛,使线程停止的事件得以传播。
另外这两个方法的区别:
interrupted()无论怎么都是指正在运行的线程。而isInterrupted()就是表示指定的线程咯。
interrupted()会清除标记,什么意思呢?就是调用interrupt()给当前线程打一个中断标记,第一次用interrupted()会返回true但是 如果不处理,之后的调用都会返回false因为它把中断标记给清了。
暂停线程相关:
suspend()与resume()【废弃】:一个暂停线程,一个恢复线程到运行状态。suspend()会暂停线程,假如当前线程为关键数据结构加锁 这时被挂起那么锁将无法释放对其他线程来说造成死锁。同时也会因为线程的暂停出现数据不同步的现象。
currentThread():该方法返回代码段正在被那个线程调用的信息。
isAlive():判断当前线程是否处于活动的状态。活动状态是指线程已经启动尚未终止的状态。线程处于正在运行或准备开始运行的状态,就认为线程是“存活”的。
sleep():在指定毫秒内让当前正在执行的线程休眠。这个“正在执行的线程”是指this.currentThread()返回的线程。
getId():取得线程的唯一标识。这个是自动分配的,且是唯一的。
yield():放弃当前的CUP资源,将它让给其他的任务去占用CPU执行时间。但是放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
8、线程的优先级
线程可以划分优先级,CPU优先执行优先级较高的线程对象中的任务。
设置线程的优先级使用setPriority()方法,该方法的源码如下:
/**
* Changes the priority of this thread.
*
* First the checkAccess
method of this thread is called
* with no arguments. This may result in throwing a
* SecurityException
.
*
* Otherwise, the priority of this thread is set to the smaller of
* the specified newPriority
and the maximum permitted
* priority of the thread's thread group.
*
* @param newPriority priority to set this thread to
* @exception IllegalArgumentException If the priority is not in the
* range MIN_PRIORITY
to
* MAX_PRIORITY
.
* @exception SecurityException if the current thread cannot modify
* this thread.
* @see #getPriority
* @see #checkAccess()
* @see #getThreadGroup()
* @see #MAX_PRIORITY
* @see #MIN_PRIORITY
* @see ThreadGroup#getMaxPriority()
*/
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,则会抛出
IllegalArgumentException异常。
JDK中使用三个常量来预定义线程的优先级:
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
线程优先级的特性:
继承性:比如A线程启动B线程,则B线程的优先级与A是一样的。设置A线程的优先级为6那么B线程也就是6。
规则性:线程优先级等级差距很大的时候,谁先执行完与代码的调用顺序无关。CPU尽量将资源让给优先级比较高的线程
随机性:优先级高的线程不一定每次都先执行完。优先级相近越能看出随机性。
优先级高的代码执行速度更快?
这是一个相对的问题,因为优先级高的会占用更多的时间片,相同的任务量能够更早的完成。或者说相同时间内可以完成更多的操作。但实际上CPU处理的速度是一样的。
9、守护线程
守护线程是一种特殊的线程,任何一个守护线程都是整个(没错是整个)JVM中所有非守护线程的“保姆”,只要当前JVM实例中存在任何一个非守护线程没有结束,守护线程就在工作,只有当最后一个非守护线程结束时,守护线程才能随着JVM一同结束工作。Daemon的作用就是为其他线程的运行提供便利服务,守护线程最经典的应用就是GC(垃圾回收器)。
让一个线程成为守护线程的方法是setDaemon(true);
java厨房_Java多线程基础相关推荐
- JAVA并发之多线程基础(2)
除了我们经常用的synchronized关键字(结合Object的wait()和notify()使用)之外,还有对应的上篇文章讲到的方法JAVA并发之多线程基础(1)之外,我们日常中使用到最多的也就是 ...
- JAVA并发之多线程基础(5)
上面介绍了并发编程中的栅栏等JAVA并发之多线程基础(4) .通过唯一的一个终点线来帮助确定线程是多晚开始执行下一次操作. LockSupport 提供了一个比较底层的线程挂起操作.有点类似于susp ...
- JAVA并发之多线程基础(4)
继上篇文章JAVA并发之多线程基础(3)谈到的信号量以及读写锁之外,接下来就继续谈及JDK中并发类的操作. CountDownLatch 倒计时器是在某一些程序需要前置处理的时候完美搭档.例如我们经常 ...
- JAVA并发之多线程基础(3)
上篇文章中讲到了重入锁以及对应的条件操作,详情见JAVA并发之多线程基础(2).这篇文章我们就继续谈JDK中含有的并发操作类. Semaphore 对于大部分的锁来说,线程之间的都是互斥的,排他的,只 ...
- java子线程的创建_Java多线程基础(一):线程的创建
多线程基础 并行与并发 并发是指一个处理器同时处理多个任务. 并行是指多个处理器或者是多核的处理器同时处理多个不同的任务. 打个比方:在并发的状态下,餐厅里只有一个厨师,尽管他做事利索,餐厅的客人等待 ...
- Java并发编程-多线程基础
Java多线程基础 1.多线程概述 实现线程的两种方式 继承Thread类 实现Runnable接口 2.线程生命周期 获取线程的名字和线程对象 3.线程的休眠 sleep方法 终止线程的休眠 强行终 ...
- 【Java程序设计】多线程基础
多线程基础 文章目录 多线程基础 一.线程的概念 (1)进程 (2)线程 二.线程的创建 (1)Thread 1.Thread类 2.Thread类的子类来创建线程 3.在新线程中完成计算某个整数的阶 ...
- java mina多线程_Java多线程基础总结九:Mina窥探(1)
一直以来的多线程的基础总结都是脱离应用的,但是要说多线程的应用就不能不说Mina.Apache Mina作为一个高性能的Java异步并发网 络通讯框架,其内部的多线程的设计和实现可谓是学习多线程的良药 ...
- java线程基础_Java多线程基础
前言 在我们工作和学习的过程中,Java线程我们或多或少的都会用到,但是在使用的过程上并不是很顺利,会遇到各种各样的坑,这里我通过讲解Thread类中的核心方法,以求重点掌握以下关键技术点: 线程的启 ...
最新文章
- Java8的集合:ArrayList的实现原理
- mysql查询操作及正则表达式小结
- Python学习笔记:面向对象高级编程(中下)
- [转]asp.net导出数据到Excel的三种方法
- 什么是 css,关于css是什么
- (转)让思维活跃化的几个技巧
- OpenHarmony 1.1.0 LTS 版本发布,十六大性能全面提升
- Visual Basic编程常见问题及解答(3)
- MySQL数据库迁移
- js 栈 html标签修复,js 打印错误堆栈
- SysTrace常识
- mysql三张表 left join
- Named Route ‘layout‘ has a default child route. When navigating to this named route (:to=“{name: ‘l
- nmea-0183数据处理matlab,Matlab分析NMEA0183报文源代码(含高斯6度带投影计算)
- 限制p元素之显示2行文字,同时出现省略号。
- Android 下拉选择框自定义view
- 在 MaCA 根目录运行所有 py 文件
- 感知器算法(PLA)
- 折半查找法的两种实现
- rs232串口通讯模块 - Delphi编程
热门文章
- logging 日志输出乱码 info_接口自动化测试中logging实际用法
- 第三方软件源_手机上的天气软件哪个更准确?
- 01初识鸿蒙_移动通讯技术的发展
- java jmf 视屏监控的核心代码_JMF(Java Media Framework)使用摄像头
- javaweb上传文件_javaWeb中,如何通过CommonsFileUpload组件上传文件
- 事物 @Transactional
- Docker部署OpenProject
- 当同时使用bootstrap-datepicker.js和jquery.validate.js这两款插件,至少要选择两次时间,才能验证成功的问题...
- Mongodb 故障分享 初始化时errmsg : exception: new file allocation failure 并且长时间处于STARTUP2...
- Strom小实例,大小写转换