并发编程的艺术读书笔记-第四章线程基础

线程6种状态

1)new:初始状态,线程被构建,但还没有调用start()方法。

2)runnable:运行状态,java中将系统的运行状态和就绪状态统称为运行状态

3)blocked:阻塞状态,表示线程阻塞于锁 (synchronized)

4)waiting:等待状态,进入该状态表示该线程需要等待其它线程作出一些动作

(中断或者通知 , object.wait())

5)TIME_WAITING:超时等待状态,该状态不同于waiting,他是可以在指定时间自动返回的  sleep导致

6)terminal:终止状态,表示当前线程已经执行完毕

注意  加synchroized导致block状态

lock导致waiting状态

daemon线程

1)main线程在启动线程daemonrunner之后随着main方法执行完毕而终止,此时java虚拟机中已经没有非daemon线程,虚拟机退出。虚拟机中所有daemon线程立即终止。

2)在构建daemon程序时,不能依靠finally块来清理资源

3)suspend() stop()在调用时不会释放资源,而是占着资源进入休眠状态,这样容易引起死锁。stop()在终结一个线程时不会释放资源,因此可能保证线程进入不正常状态

等待/通知机制

1 基本流程

1)使用wait() notify() notifyall()时需要先对对象加锁。

2)调用wait()方法后,线程状态由runnable 变成waiting状态,并将当前线程放到当前对象的等待队列中

3)notify()或notifyall()方法调用后,等待线程依旧不会从wait()中返回,需要调用notify()或者notifyall()的线程释放锁后,等待线程才有机会从wait()中返回

4)notify()方法是将线程从等待队列放入到同步队列中,而nofityall()方法是将所有的等待线程从等待队列中放入同步队列,被移动的线程从waiting状态变为blocked状态

5)从wait()对象返回的前提是获得了对象的锁

2 经典伪代码

等待方伪代码

1)synchronized(对象){

while(判断条件不足){

对象.await();

doSomeThing();

唤醒方伪代码

2) synchronized(对象){

判断满足条件

对象.notify();

3管道输入输出流

管道输入/输出流和普通文本输入输出流或者网络输入/输出流的不同之处在于,他主要用于线程之间的数据传输,主要介质为内存

out.conn

4join()方法的使用

如果一个线程a使用了 thread.join()那么它的含义是当前线程a等待thread线程终止后才从join()方法返回

5 等待超时

调用某个方法时等待一段时间,如果该方法能够在给定的时间内返回结果,那么将结果立刻返回,反之则返回默认结果

伪代码

public synchronized Object get(long millons){

long future = system.millons+millons

long remaining=millons;

while(result==null&&remaining>0){

wait(remaining);

remaining=future-system.millons;

}

return result;

}

6 线程安全的连接池实例

public class ConnectionPool{

private LinkedList pool = new LinkedList();

private static int initCapacity=10;

public ConnectionPool(){

//初始化连接池

for(int i=0;i<initCapacity;i++){

pool.addLast(ConnectionDriver.getConnection());

}

}

//释放连接池

public void  ReleaseConnection(Connection connection){

Synchronized(pool){

pool.addLast(connection);

this.notify();

}

}

}

//获取连接池

public Connection fetchConnection(long millons){

long remaining = millons;

long future = System.currentMillons+millons;

Synchronized(pool){

while(pool.isempty()&&remaining>0){

pool.wait(millons);

remaining= System.currentMillons-future;

}

Connection conn=null;

if(!pool.isEmpty()){

conn = pool.removeFirst();

}

return conn;

}

}

时间: 2024-07-31 06:32:43

并发编程的艺术读书笔记-第四章线程基础的相关文章

&lt;java并发编程的艺术&gt;读书笔记-第三章java内存模型(一)

一概述 本文属于<java并发编程的艺术>读书笔记系列,继续第三章java内存模型. 二重排序 2.1数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性.数据依赖分下列三种类型: 名称 代码示例 说明 写后读 a = 1;b = a; 写一个变量之后,再读这个位置. 写后写 a = 1;a = 2; 写一个变量之后,再写这个变量. 读后写 a = b;b = 1; 读一个变量之后,再写这个变量. 上面三种情况,只要重排序两个操作的执行顺序,

《利用python进行数据分析》读书笔记--第四章 numpy基础:数组和矢量计算

第四章 Numpy基础:数组和矢量计算 实话说,用numpy的主要目的在于应用矢量化运算.Numpy并没有多么高级的数据分析功能,理解Numpy和面向数组的计算能有助于理解后面的pandas.按照课本的说法,作者关心的功能主要集中于: 用于数据整理和清理.子集构造和过滤.转换等快速的矢量化运算 常用的数组解法,如排序.唯一化.集合运算等 高效的描述统计和数据聚合/摘要运算 用于异构数据集的合并/连接运算的数据对齐和关系型数据运算 将条件逻辑表述为数组表达式(而不是带有if-elif-else分支

synchronized的实现原理-java并发编程的艺术读书笔记

1.synchronized实现同步的基础 Java中的每个对象都是可以作为锁,具体有3种表现. 1.对于普通同步方法,锁是当前实例对象. 2.对于静态同步方法,锁是当前类的Class对象. 3.对于同步方法块,锁是Synchonized括号里面的配置对象. 当前一个线程试图访问同步代码块时,它首先必须得到锁,退出或者抛出异常时候必须释放锁.那么锁到底存在什么地方? 从JVM规范可以看到Synchonized在JVM里的实现原理,JVM基于进入和退出Monitor对象来实现方法同步和代码快同步,

Windows核心编程读书笔记-第六章线程基础

1.相较于线程,进程所使用的系统资源更多.其原因在于地址空间.为一个进程创建一个虚拟的地址空间需要大量系统资源.线程只有一个内核对象和一个栈. 2.线程的入口函数 DWORD WINAPI ThreadFunc(PVOID pvParam){ DWORD dwResult = 0; ... return(dwResult); } 线程函数的几点说明 线程函数可以任意命名. 线程函数只有一个参数,而其意义由我们(而非操作系统)来定义.因此,我们不必担心ANSI/Unicode问题. 线程函数必须返

《Java并发编程实战》读书笔记

Subsections 线程安全(Thread safety) 锁(lock) 共享对象 对象组合 基础构建模块 任务执行 取消和关闭 线程池的使用 性能与可伸缩性 并发程序的测试 显示锁 原子变量和非阻塞同步机制 一.线程安全(Thread safety) 无论何时,只要多于一个线程访问给定的状态变量.而且其中某个线程会写入该变量,此时必须使用同步来协助线程对该变量的访问. 线程安全是指多个线程在访问一个类时,如果不需要额外的同步,这个类的行为仍然是正确的. 线程安全的实例: (1).一个无状

《Java并发编程实战》读书笔记(一)----- 简介

简史 早期的计算机中不包含操作系统,从头至尾都只执行一个程序,并且这个程序能访问计算机所有资源.随着计算机发展,操作系统的出现,使得计算机可以同时运行多个程序,并且每程序都在单独的进程内运行.为什么要这么做呢?主要基于以下原因: 1.资源利用率 程序在等待时计算机可以执行另一个程序,同一个资源可以被不同程序使用,这无疑提高了资源的利用率.2.公平性 不同的用户与程序对计算机有相同的使用权,通过时间分片每个程序共享资源,而不是等待上一个程序运行结束再启动下一个程序.3.便利性 每个程序单独运行,必

《java并发编程实战》读书笔记9--并发程序的测试

第12章 并发程序的测试 大致分为两类:安全性测试和活跃性测试 12.1 正确性测试 找出需要检查的不变性条件和后验条件.接下来将构建一组测试用例来测试一个有界缓存.程序清单12-1给出了BoundedBuffer的实现,其中使用Semaphore来实现缓存的有界属性和阻塞行为. BoundedBuffer实现了一个固定长度的队列,其中定义了可阻塞的put和take方法,并通过两个计数信号量进行控制.(实际情况中如果需要一个有界缓存,应该直接使用ArrayBlockingQueue或者Linke

《java并发编程实战》读书笔记2--对象的共享,可见性,安全发布,线程封闭,不变性

这章的主要内容是:如何共享和发布对象,从而使它们能够安全地由多个线程同时访问. 内存的可见性 确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化. 上面的程序中NoVisibility可能会持续循环下去,因为读线程可能永远都看不到ready的值.一种更奇怪的现象是NoVisibility可能会输出0,因为读线程可能看到了写入ready的值,但却没有看到之后写入number的值,这种现象被称为"重排序".多线程之指令重排序 失效数据 简而言之就是在缺乏同步的程序中可能会读取到

《Linux内核设计与实现》读书笔记 第四章 进程调度

第四章进程调度 进程调度程序可看做在可运行太进程之间分配有限的处理器时间资源的内核子系统.调度程序是多任务操作系统的基础.通过调度程序的合理调度,系统资源才能最大限度地发挥作用,多进程才会有并发执行的效果. 最大限度地利用处理器时间的原则是,只要有可以执行的进程,那么总会有进程在执行. 4.1多任务 多任务操作系统就是能同时并发地交互执行多个进程的操作系统.多任务能使多个进程处于堵塞或者睡眠状态.就是任务位于内存内但是不被执行,直到某一事件发生. 分类: l  非抢占式:除非进程自己主动停止运行