【Java并发学习】之详解线程的点滴(1)
2017-11-12 23:02
495 查看
【Java并发学习】之详解线程的点滴(1)
前言
在前面的几个小节中,我们粗略地学习了线程的基本概念,定义任务的方式,并且通过Java中的多线程API来驱动对应的任务,然后学习了线程的互斥与同步关系,线程之间进行资源共享后的同步操作等等一些简单的内容,可以说,线程中的主要内容我们已经掌握了,然而,也仅仅只是简单内容,很多比较细节、复杂的东西在之前我们刻意避开了,接下来的几个小节中,我们就来具体地学习线程的各个细节内容线程的属性
线程有许多的属性,比如线程的ID、名字、优先级、状态等,接下来我们就来具体学习这些属性线程的ID
每个线程都有对应的独一无二的ID,这些ID是由JVM在运行的时候为线程设置的,用于区分不同的线程,并且不对外提供设置线程ID的接口,也就是说,在Java中,我们仅能够获取多线程的ID,而不能设置线程的ID,访问代码如下
class DetailTask implements Runnable{ @Override public void run() { System.out.println("Details : " + Thread.currentThread().getId()); // 其中Thread.currentThread()用于获取当前执行的线程 // 通过thread.getId()则可以获取对应的线程的ID } }
线程的名字
在线程比较多的情况下,我们会倾向于根据执行不同任务的不同线程来为其设置名字,方便在日志以及其他场景中使用到,设置以及获取线程的名字操作具体如下
class DetailTask implements Runnable{ private static int cnt = 0; // 注意这里的代码是非线程安全的 @Override public void run() { Thread.currentThread().setName("Thread " + cnt++); // 设置线程名字 System.out.println("Details : " + Thread.currentThread().getName()); // 获取线程的名字 } }
线程优先级
优先级是一个比较有价值的概念,在Java中,线程之间的调度采用的是基于时间片的轮转调度方式,其中在线程进行切换,重新调度时,调度的主要依据就是优先级,通常来说,优先级比较高的线程,被调度的可能性会比较大,也就是说,在单位时间内,优先级高的线程被调度的次数会大于优先级低的线程
不过,在设置线程的优先级的时候,需要注意一下几点
线程的有效优先级仅能为 0 - 10 之间的整数,其他数字则会抛出
java.lang.IllegalArgumentException
由于不同的操作系统的优先级的范围不一致,而映射到0-10之间则会出现一些意想不到的惊喜,所以一般在设置优先级的时候,不能过分依赖于优先级,尽量只使用
Thread.MAX_PRIORITY、
Thread.MIN_PRIORITY以及默认的优先级,分别对应的数值为10,0,1
设置优先级仅仅仅能提高线程被调度的概率,也就是仅能提高线程被调度的次数,但是并不能保证执行次数一定会高,所以,不能仅依赖优先级来实现如同步、合作之类的操作
优先级的设置必须在线程启动之前设置,也就是必须在thread.start()方法执行之前进行设置,否则,会采用默认的优先级,言下之意即不能在run方法中进行优先级的设置
for (int i = 0; i < 10; i++){ Thread thread = new Thread(task); System.out.println("Priority " + thread.getPriority()); if (i % 2 == 0){ thread.setPriority(Thread.MIN_PRIORITY); // 设置优先级为最低 }else { thread.setPriority(Thread.MAX_PRIORITY); // 设置优先级为最高 } thread.start(); }
线程的状态
通常来讲,线程的数量是多于CPU的数量,这也就意味着,为了保证每个线程都能得到执行,在特定时刻,总会有线程处于非运行状态,当然,Java中线程的状态不止这两种,具体如下
NEW:新建状态,此时线程已经被赋予了任务,但需要注意的是,此时执行该线程所需要的资源仍未准备好,是不具备执行条件的,也就是在调用start()方法之前的状态
RUNNABLE:可运行状态,表明此时该线程已经是处于可执行的状态,这里需要注意的是,可运行状态可以是该线程正在执行,也可能该线程的除了CPU之外的其他资源都已经准备完毕,只要分配给其CPU就能执行。注意是
Runnable而不是
Run
BLOCKED:阻塞状态,线程如果处于该状态,则表明此时该线程正在等在某个锁的释放
WAITING:等待状态,表明此时该线程正在等待某些其他线程的资源,通常是调用了
Object.wait()、
join()、
LockSupport.park()这几个方法
TIMED_WAITING:等待超时状态,同样是等待状态,只是多了个计时器,通常是调用了上面几个方法中带时间参数的重载方法
TERMINATED:中断/结束状态,表明此时该线程已经处于执行完毕的状态或者是被其他线程或者JVM中断,结束其运行
关于这几个状态的详细介绍,可以参考JDK源码中的注释
/* A thread can be in only one state at a given point in time. * These states are virtual machine states which do not reflect * any operating system thread states. * * @since 1.5 * @see #getState */ public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
守护线程
上面我们主要学习了线程的几个属性,ID、名字、优先级、状态等,接下来我们来学习一个新的概念,守护线程守护线程是一类特殊的线程,主要的特点如下
被调度的频率较低
当当前系统中的所有非守护线程结束时,守护线程也会结束,而且不管正在执行什么任务
基于守护线程的特点,在使用的时候需要注意,不能在守护线程中做一些逻辑比较复杂的操作,不能做一些比较重要的操作
一个典型的使用守护线程的例子就是JVM中的垃圾回收器
public static void main(String[] args) { Thread daemonTask = new Thread(new DaemonTask()); daemonTask.setDaemon(true);// 设置为守护线程,这里同样需要注意,必须在线程启动之前进行设置 daemonTask.start(); } class DaemonTask implements Runnable{ @Override public void run() { while (true){ System.out.println("I'm Daemon thread"); } } }
总结
本小计我们主要学习了线程的相关属性,包括了ID、名字、优先级、状态,以及守护线程的概念和设置守护线程的方法,线程中的异常处理,接下来我们将学习线程的中断以及线程的异常处理等等的内容相关文章推荐
- 【Java并发学习】之详解线程的点滴2
- Java并发学习之线程状态及Thread常用方法详解
- 张孝祥java.concurrent线程并发学习笔记 - 传统线程回顾
- Java并发学习笔记(7)线程的同步 (锁)
- Java并发学习笔记(4)线程的取消,关闭和异常终止
- Java并发学习之二——获取和设置线程信息
- Java核心知识点学习----多线程并发之线程间的通信,notify,wait
- 张孝祥java.concurrent线程并发学习笔记 - concurrent简介
- Java并发学习之六——等待线程的终结
- Java并发学习之十——用线程工厂创建线程
- Java并发学习笔记(5)停止基于线程的服务
- Java并发学习之中的一个——线程的创建
- Java并发学习之七——守护线程
- Java并发学习之八——在线程中处理不受控制的异常
- Java并发学习笔记(13)线程之间的协作(Object.wait(),notifu(),notifyAll() Thread.join())
- java学习——java高级特性,线程,并发 笔记
- Java并发学习笔记(16)守护线程,线程组
- java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器
- Java并发学习之四——操作线程的中断机制
- JAVA的线程学习、并发线程的学习