[TOC]
一般来讲,线程内部有自己私有的线程上下文,互不干扰。但当我们需要多个线程相互协作时,就需要利用线程间的通信。以下介绍几种常用的通信机制。
记录学习历程
[TOC]
在现代操作系统中,线程被视为轻量级进程,所以操作系统中线程的状态其实是和操作系统中进程的状态是一致的。
操作系统中线程主要有三个状态:
[TOC]
Java使用ThreadGoup
来表示线程组,我们可以使用线程组对线程进行批量控制。
每个Thread
必然存在于一个ThreadGroup
中,Thread
不能独立于ThreadGroup
存在。执行main()
方法的主线程所在的线程组名字为”main”,如果我们new Thread()
时不指定线程组,那么默认将父线程 (当前执行new Thread
) 的线程组设为自己的线程组。举例:
1 | public class ThreadTest { |
结果为:
HashMap
的类定义如下:
1 | public class HashMap<K,V> extends AbstractMap<K,V> |
HashMap
继承自AbstractMap
抽象类,实现了Map
接口、Cloneable
接口和Serializable
接口。
HashMap
是基于哈希表的Map
接口实现,是以key-value
存储形式存在,主要用来存储键值对。HashMap
的实现不是同步的,即意味着不是线程安全的。HashMap
的键、值都可以为null
。此外,HashMap
的映射不是有序的。
JDK1.8以前,HashMap
由数组+链表组成,数组是HashMap
的主体,链表则是为了解决哈希冲突(两个对象调用的hashCode()
方法计算得到的哈希值一致导致计算的数组索引相同),(使用“拉链法”解决冲突)。
JDK1.8以后解决哈希冲突时发生了较大变化。当链表长度大于阈值(或者红黑树边界值,默认为8)并且当前数组长度大于64时,此时此索引上的所有数据采用红黑树存储。
Map接口继承关系如下:
[TOC]
Thread
类和Runnable
接口Java中,JDK提供了Thread
类和Runnable
接口,我们有两种方法来实现自己的线程类。
Thread
类,并重写run
方法。Runnable
接口的run
方法。[TOC]
进程
进程就是应用程序在内存中分配的空间,也就是正在运行的程序,是系统运行程序的基本单位。
在Java中,当我们启动main
函数时其实就是启动了一个JVM
进程,而main
函数所在的线程就是这个进程中的一个线程,叫做主线程。
线程
线程是一个比进程更小的执行单位,一个进程在执行过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在各个线程间切换工作时,负担会比进程小得多,因此线程也被称为轻量级进程。
线程是一个比进程更小的执行单位,一个进程在其执行过程中可以产生多个线程。
进程是一个独立的运行环境,而线程是其中执行的一个任务,他们间本质的区别是是否单独占有内存地址以及其他系统资源(比如 I/O)。
上下文切换是指CPU从一个进程(或线程)切换到另一个进程(或线程)。上下文是指某一时间点CPU寄存器和程序计数器的内容。
CPU通过为每个线程分配CPU时间片来实现多线程机制。CPU通过时间片分配算法来循环执行任务,当前执行一个时间片后会切换到下一个任务。
但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态,所以任务从保存到再加载的过程就是一次上下文切换。
LinkedList
是Java集合中List
接口的一个重要实现类,其底层使用的是双向链表,所以不支持随机访问。基本结点定义如下:
1 | private static class Node<E> { |
LinkedList
类实现了List
接口和Deque
接口,所以可以当成一个队列使用。定义如下:
1 | public class LinkedList<E> |
默认的构造函数
1 | /** |
由上述代码可知,当我们创建一个ArrayList
时,如果不传入参数,会使用初始容量10构造一个空数组,只有当真正对数组进行添加元素操作时才会分配容量。即向数组中添加第一个元素时,数组容量扩容为10.
如果代码要完成的计算无法放在一个表达式中,可以把代码放在{}中。
1 | Arrays.sort(str, (String first,String second) -> (return (first.length()-second.length())) |
即使lambda
无参数,也要提供空括号.
1 | ()-> {for(int i=0;i<10;i++) System.out.println(i);} |
如果可以推导出一个lambda
的参数类型,则可以忽略参数类型
1 | Arrays.sort(friends,(first,second) -> (first.length()-second.length()));//friends是一个字符串数组 |
无需指定lambda的返回值类型,返回值类型会由上下文推导得到
1 | (String str1,String str2) -> str1.length()-str2.length(); |