flbu blog

记录学习历程


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

  • 搜索

Java多线程-线程间的通信

发表于 2020-04-13 | 分类于 Java多线程

[TOC]

一般来讲,线程内部有自己私有的线程上下文,互不干扰。但当我们需要多个线程相互协作时,就需要利用线程间的通信。以下介绍几种常用的通信机制。

阅读全文 »

Java线程的状态与主要转换方法

发表于 2020-04-10 | 分类于 Java多线程

[TOC]

操作系统中的线程状态转换

在现代操作系统中,线程被视为轻量级进程,所以操作系统中线程的状态其实是和操作系统中进程的状态是一致的。

操作系统中线程状态转换.png

操作系统中线程主要有三个状态:

  • 就绪状态(ready):线程正在等待使用CPU,等分配到CPU时间片就可以进入running状态。
  • 执行状态(running):线程正在使用CPU。
  • 等待状态(waiting):线程经过等待事件的调用或者正在等待其他资源,如 I/O等。
阅读全文 »

Java多线程-线程组和线程优先级

发表于 2020-04-09 | 分类于 Java多线程

[TOC]

线程组与线程优先级

线程组

Java使用ThreadGoup来表示线程组,我们可以使用线程组对线程进行批量控制。

每个Thread必然存在于一个ThreadGroup中,Thread不能独立于ThreadGroup存在。执行main()方法的主线程所在的线程组名字为”main”,如果我们new Thread()时不指定线程组,那么默认将父线程 (当前执行new Thread) 的线程组设为自己的线程组。举例:

1
2
3
4
5
6
7
8
9
public class ThreadTest {
public static void main(String[] args) {
new Thread(() -> {
System.out.println("当前线程组名称: " + Thread.currentThread().getThreadGroup().getName());
System.out.println("当前线程名称: " + Thread.currentThread().getName());
}).start();
System.out.println("main方法所在线程的线程组名称: " + Thread.currentThread().getThreadGroup().getName());
}
}

结果为:

结果

阅读全文 »

HashMap源码学习

发表于 2020-04-07 | 分类于 源码学习

HashMap源码学习

HashMap集合简介

HashMap的类定义如下:

1
2
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable

HashMap继承自AbstractMap抽象类,实现了Map接口、Cloneable接口和Serializable接口。

HashMap是基于哈希表的Map接口实现,是以key-value存储形式存在,主要用来存储键值对。HashMap的实现不是同步的,即意味着不是线程安全的。HashMap的键、值都可以为null。此外,HashMap的映射不是有序的。

JDK1.8以前,HashMap由数组+链表组成,数组是HashMap的主体,链表则是为了解决哈希冲突(两个对象调用的hashCode()方法计算得到的哈希值一致导致计算的数组索引相同),(使用“拉链法”解决冲突)。

JDK1.8以后解决哈希冲突时发生了较大变化。当链表长度大于阈值(或者红黑树边界值,默认为8)并且当前数组长度大于64时,此时此索引上的所有数据采用红黑树存储。

Map接口继承关系如下:

Map接口继承关系.png

阅读全文 »

Java多线程入门类与接口

发表于 2020-04-06 | 分类于 Java多线程

[TOC]

Java入门类和接口

Thread类和Runnable接口

Java中,JDK提供了Thread类和Runnable接口,我们有两种方法来实现自己的线程类。

  • 继承Thread类,并重写run方法。
  • 实现Runnable接口的run方法。
阅读全文 »

Java多线程-进程与线程

发表于 2020-04-06 | 分类于 Java多线程

[TOC]

进程与线程

概念

  • 进程

    进程就是应用程序在内存中分配的空间,也就是正在运行的程序,是系统运行程序的基本单位。

    在Java中,当我们启动main函数时其实就是启动了一个JVM进程,而main函数所在的线程就是这个进程中的一个线程,叫做主线程。

  • 线程

    线程是一个比进程更小的执行单位,一个进程在执行过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在各个线程间切换工作时,负担会比进程小得多,因此线程也被称为轻量级进程。

线程与进程的区别

线程是一个比进程更小的执行单位,一个进程在其执行过程中可以产生多个线程。

进程是一个独立的运行环境,而线程是其中执行的一个任务,他们间本质的区别是是否单独占有内存地址以及其他系统资源(比如 I/O)。

  • 进程间存在内存隔离,数据是分开的,数据共享复杂但同步简单,各个进程间互不干扰;而线程共享进程占有的内存地址空间和资源,数据共享简单但同步复杂。
  • 进程的创建和销毁开销较大,而线程的开销较小。
  • 进程间通信比较复杂,线程间通信比较简单。
  • 进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位,即CPU分配时间的单位。

上下文切换

上下文切换是指CPU从一个进程(或线程)切换到另一个进程(或线程)。上下文是指某一时间点CPU寄存器和程序计数器的内容。

CPU通过为每个线程分配CPU时间片来实现多线程机制。CPU通过时间片分配算法来循环执行任务,当前执行一个时间片后会切换到下一个任务。

但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态,所以任务从保存到再加载的过程就是一次上下文切换。

LinkedList源码学习

发表于 2020-03-29 | 分类于 源码学习

LinkedList源码学习

内部结构

LinkedList是Java集合中List接口的一个重要实现类,其底层使用的是双向链表,所以不支持随机访问。基本结点定义如下:

1
2
3
4
5
6
7
8
9
10
11
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;

Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}

LinkedList类实现了List接口和Deque接口,所以可以当成一个队列使用。定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
transient int size = 0;
{
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;

/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;

......

}
阅读全文 »

ArrayList源码学习

发表于 2020-03-26 | 分类于 源码学习

ArrayList源码学习

ArrayList的构造函数

  • 默认的构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    /**
    * Constructs an empty list with an initial capacity of ten.
    */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    由上述代码可知,当我们创建一个ArrayList时,如果不传入参数,会使用初始容量10构造一个空数组,只有当真正对数组进行添加元素操作时才会分配容量。即向数组中添加第一个元素时,数组容量扩容为10.

    阅读全文 »

lambda表达式

发表于 2019-11-24 | 分类于 Java

lambda表达式

格式:参数 -> (表达式)

如果代码要完成的计算无法放在一个表达式中,可以把代码放在{}中。

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();
阅读全文 »
<i class="fa fa-angle-left"></i>123

flbu

flbu的技术博客

29 日志
8 分类
23 标签
RSS
GitHub E-Mail
0%
© 2022 flbu
本站总访问量次