读书笔记——Java并发线程编程实战

KV Cache 详解:新手也能理解的 LLM 推理加速技巧 (Autoregressive)生成的,即每次生成一个 token,然后将其作为输入继续生成下一个 token。:如果序列太长,超过了 KV Cache 的存储限制,就需要丢弃最早的 tokens(类似滑动窗口)。时,每次只会生成一个新 token,然后再把这个 token 作为输入继续生成下一个 token。,只缓存计算过的 K,VK, V,每次只计算新 token 的 K,VK, V,从而提升推理效率。:如果输入的 prompt 发生变化,之前的 KV Cache 不能复用,必须重新计算。 阅读详情

Java并发线程编程实战

第1章 简介 略

第2章 线程安全性

概念
  1. 线程安全类:当多个线程访问某个类时,这个类始终都能表现出正确的行为。
    举例:无状态对象一定是线程安全的。比如servlet。
  2. 竞态条件:由于不恰当的执行时序而出现不正确的结果。
    举例:先检查后执行:基于一种可能失效的观察结果来做出判断或者执行某个计算
  3. 复合操作:比如在一个无状态的类中对于一个状态变量进行递增运算进行(读取——修改——写入)操作时必须原子化,例如使用atomic包下的一些原子变量类
  4. 锁保护:对于可能被多个线程同时访问的可变状态变量,在访问它时都需要持有同一个锁,在这种情况下,我们称状态变量是由这个锁保护的。
  5. 注意:当执行时间较长的计算或者可能无法快速完成的操作时(例如,网络I/O或控制台I/O),一定不要持有锁。

第3章 对象的共享

可见性

非原子性的64位操作:
非volatile类型的64位数值变量double、 long,JVM允许将64位的读操作或写操作分解为两个32位的操作,当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位。

加锁的含义:
不仅仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步

正确使用volatile变量的方式:
1. 当变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值;
2. 该变量不会与其他状态变量一起纳入不变性条件中;
3. 在访问变量时不需要加锁。

加锁机制和volatile变量的区别:
加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。

线程封闭

概念:不共享数据
**分类:**Ad-hoc线程封闭、栈封闭、ThreadLocal类
栈封闭:指的是局部变量封闭在执行线程中
ThreadLocal类:这个类能使线程中的某个值与保存值的对象关联起来,通常用于防止对可变的单实例变量或全局变量进行共享。

不变性

概念:不可变对象一定是线程安全的
对象不可变必须满足以下条件:
- 对象创建以后其状态就不能修改
- 对象的所有域都是final类型
- 对象时正确创建的(在对象的创建期间,this引用没有逸出)

final域
final域能够确保初始化过程的安全性,从而可以不受限制地访问不可变对象,并在共享这些对象时无需同步

安全发布

安全发布的常用模式:
- 在静态初始化函数中初始化一个对象引用:例如 public static Holder holder = new Holder(42);
- 将对象的引用保存到volatile类型的域或者AtomicReference对象中
- 将对象的引用保存到某个正确构造对象的final类型域中
- 将对象的引用保存到一个由锁保护的域中

对象的发布需求取决于它的可变性:
- 不可变对象可以通过任意机制来发布
- 事实不可变对象必须通过安全方式来发布
- 可变对象必须通过安全方式来发布,并且必须是线程安全的或者由某个锁保护起来

实用策略
  • 线程封闭。线程封闭的对象只能由一个线程拥有,对象封闭在该线程中,并且只能由这个线程修改。
  • 只读共享。在没有额外同步的情况下,共享的只读对象可以由多个线程并发访问,但任何线程都不能修改它。共享的只读对象包括不可变对象和事实不可变对象。
  • 线程安全共享。线程安全的对象在其内部实现同步,因此多个线程可以通过对象的公有接口来进行访问而不需要进一步的同步。
  • 保护对象。被保护的对象只能通过持有特定的锁来访问。保护对象包括封装在其他线程安全对象中的对象,以及已发布的并且由某个特定锁保护的对象。

第4章 对象的组合

实例封闭

将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁。
**举例:**Java平台类库提供了很多线程封闭的实例,就是讲非线程安全的类转化为线程安全的类,比如sychronizedList和concurrentHashMap。

Java监视器模式:将对象所有的可变状态封装起来,并由自己的内置锁来保护。比如Vector和HashTable。

@ThreadSafe
public final class Counter {
    @GuardedBy("this") private long value = 0;
    public synchronized long getValue() {
        return value;
    }
    public synchronized long increament() {
        if (value == Long.MAX_VALUE) {
            throw new IllegalStateException("counter overflow");
        }    
        return ++value;
    }
}
线程安全性委托

如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效状态转换,那么可以将线程安全性委托给底层的状态变量。

在现有的线程安全类中添加功能

客户端加锁机制:对于使用某个对象X的客户端代码,使用X本身用户保护其状态的锁来保护这段客户代码。

第5章 基础构建模块

同步容器类:Vector,HashTable

vector的问题:
比如getLats()、deleteLast()法交替执行时会抛出ArrayIndexOutOfBoundsException异常

迭代器的问题:
容器在迭代过程中被修改时,就会抛出ConcurrentModificationException异常

并发容器:concurrentHashMap和CopyOnWriteArrayList
同步工具类:阻塞队列,信号量Semaphore,栅栏Barrier,闭锁Latch

概念:它们封装了一些状态,这些状态将决定执行同步工具类的线程是继续执行还是等待,此外还提供了一些方法对状态进行操作,以及另一些方法用于高效地等待同步工具类进入到预期状态。

闭锁:闭锁可以用来确保某些活动直到其他活动都完成后才继续执行
信号量:用来控制同时访问某个特定资源的操作数量,或者执行某个指定操作的数量。
栅栏:栅栏与闭锁的关键区别在于,所有线程必须同时的到达栅栏位置,才能继续执行。闭锁用于等待时间,而栅栏用于等待线程。

第6章 任务执行

Executor框架

示例:基于Executor的Web服务器

class TaskExecutionWebServer {
    private static final int NTHREADS = 100;
    private static final Executor exec = Executors.newFixedThreadPool(NTHREADS);
    public static void main (String[] args) throws IOException {
        ServerSocket socket = new ServerSocket(80);
        while(true) {
            final Socket connection = socket.accept();
            Runnable task = new Runnable() {
                public void run() {
                    handleRequest(connection);
                }
            };
            exec.execute(task);
        }
    }
}

线程池:
- newFixedThreadPool:返回通用的ThreadPool-Executor实例
- newCachedThreadPool:返回通用的ThreadPool-Executor实例
- newSingleThreadExecutor
- newScheduledThreadPool

ExecutorService的生命周期:
- 运行
- 关闭
- 已终止

延迟任务与周期任务:使用ScheduledThreadPoolExecutor来代替Timer。
原因:
1. Timer在执行所有定时任务时只会创建一个线程
2. 不会捕获异常,并会终止定时任务

携带结果的任务Callable与Future
- 与Runable的区别:可以返回一个值或者一个受检查的异常
- Future表示一个任务的生命周期

示例:利用Future和CompletionService实现页面渲染器

为任务设置时限:
如果某个任务无法在指定时间内完成,那么将不再需要它的结果,此时可以放弃这个任务

示例:旅行预订门户网站

第7章 取消与关闭

任务取消

中断:

//Thread中的中断方法
public class Thread {
    //中断目标线程
    public void interrupt(){}
    //返回目标线程的中断状态
    public boolean isInterrupt(){}
    //清楚当前线程的中断状态,返回它之前的值
    public static boolean interrupted(){}
}

对中断操作的正确理解:它并不会真正地中断一个正在运行的线程,而是发出中断请求,然后由线程在下一个合适的时刻中断自己。

响应中断:
处理InterruptedException:
- 传递异常(可能在执行某个特定于任务的清除操作之后),从而使你的方法也成为可中断的阻塞方法
- 恢复中断状态,从而使调用栈中的上层代码能够对其进行处理

通过Future来实现取消:

public static void timedRun(Runnable r, long timeout, TimeUnit unit) throws InterruptedException {
    Future<?> task = taskExec.submit(r);
    try {
        task.get(timeout, unit);
    } catch (TimeoutException e) {
        //接下来任务将被取消
    } catch (ExecutionException e) {
        //如果在任务中抛出了异常,那么重新抛出该异常
        throws launderThrowable(e.getCause());
    } finally {
        //如果任务已经结束,那么执行取消操作也不会带来任何影响
        task.cancel; //如果任务正在运行,那么将被中断
    }
}
停止基于线程的服务

毒丸对象:是指一个放在队列上的对象,其含义是当得到这个对象时,立即停止。在FIFO队列中,毒丸对象将确保消费者在关闭之前首先完成队列中的所有工作,在提交毒丸对象之前的提交的所有工作都会被处理,而生产者在提交了毒丸对象之后,将不会再提交任何工作。

public class IndexingService {
    private static final File POISON = new File("");
    private final IndexingThread consumer = new IndexerThread();
    private final CrawlerThread producer = new CrawlerThread();
    private final BlockingQueue<File> queue;
    private final FileFilter fileFilter;
    private final File root;

class CrawlerThread extends Thread {}
class IndexerThread extends Thread{}

    public void start() {
        producer.start();
        consumer.start();
    }
    public void stop() {
        producer.interrupt();
    }
    public void awaitTermination() throws InterruptException {
        consumer.join();
    }
}
处理非正常的线程终止

未捕获异常:
当一个线程由于未捕获异常而退出时,JVM会把这个事件报告给应用程序提供的UncaughtExceptionHandler异常处理器。如果没有提供任何异常处理器,那么默认的行为是将栈追踪信息输出到System.err。

JVM关闭

关闭钩子:
在正常关闭中,JVM首先调用所有已注册的关闭钩子,指的是通过Runtime.addShutdownHook注册的但尚未开始的线程。

注意:对所有服务使用同一个关闭钩子(而不是每个服务使用一个不同的关闭钩子),并且在该关闭钩子中执行一系列的关闭操作。这确保了关闭操作在单个线程中串行执行,从而避免了在关闭操作之间出现竞态条件或死锁等问题。

守护线程:执行一些辅助性工作,但又不阻碍JVM的关闭的线程。
与普通线程的区别:仅在于退出时发生的操作,当一个线程退出时,JVM会检查其他正在运行的线程,如果这些线程都是守护线程,那么JVM会正常退出操作。当JVM停止时,所有仍然存在的守护线程都将被抛弃——既不会执行finally代码块,也不会执行回卷栈,而JVM只是直接退出。

注意:守护线程最好用于执行“内部”任务,例如周期性地从内存的缓存中移除逾期的数据。

第8章 线程池的使用

配置ThreadPoolExecutor

通用构造函数:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {}

管理队列任务:
- 有界队列
- 无界队列
- 同步移交

饱和策略:ThreadPoolExecutor的饱和策略可以通过调用setRejectedExecutionHandler来修改。
- AbortPolicy
- CallerRunsPolicy
- DiscardPolicy
- DiscardOldestPolicy

ThreadFactory:每当线程池需要创建一个线程时,都是通过线程工厂方法来完成的,即newThread()方法。

第9章 图形用户界面应用程序 略

第10章 避免活跃性危险

死锁

锁顺序死锁:两个线程试图以不同的顺序来获得同样的锁
动态锁顺序死锁:如果两个线程同时调用thransferMoney,其中一个线程从X向Y转账,另一个线程从Y向X转账,那么就会发生死锁
在协作对象之间发生的死锁
开放调用:调用某个方法时不需要持有锁

死锁的避免与诊断
  • 支持定时的锁
  • 通过线程转储信息来分析死锁
其他活跃性危险

饥饿:当线程由于无法访问它所需要的资源而不能继续执行时。
糟糕的响应性
活锁:线程不断重复执行相同的操作,而且总会失败
例子:活锁通常发生在处理事务消息的应用程序中,如果不能成功地处理某个消息,那么消息处理机制将会回滚整个事务,并将它重新放回队列的开头。
解决方法:在重试机制中引入随机性

第11章 性能与可伸缩性

Amdahl定律:

定律:在增加计算资源的情况下,程序在理论上能够实现最高加速比,这个值取决于程序中并行组件与串行组件所占的比重

线程引入的开销

上下文切换:如果可运行的线程大于cpu的数量,那么操作系统最终会将某个正在运行的线程调度出来,从而使其他线程能够使用cpu,这将导致一次上下文切换,在这个过程中将保存当前运行线程的执行上下文,并将重新调度进来的线程的执行上下文设置为当前上下文。

内存同步:
阻塞:可以通过自旋等待或者被挂起

减少锁的竞争
  • 缩小锁的范围(快进快出)
  • 减小锁的粒度
  • 锁分段:比如concurrentHashMap
  • 避免热点域:缓存一些反复计算的结果
  • 一些替代独占锁的方法:使用并发容器、读写锁、不可变对象和原子变量
  • 监测cpu的利用率

第12章 并发程序的测试(略)

第13章 显式锁

Lock和ReentrantLock
  • 轮询锁与定时锁:通过tryLock方法实现,避免死锁的发生
  • 可中断的锁等待:能在可取消的操作中使用加锁
  • 公平队列
  • 非块结构的加锁
性能考虑因素

在Java5.0中,ReentrantLock能提供更高的吞吐量,但在Java6.0中,二者的吞吐量非常接近。

公平性

大多数情况下,非公平锁的性能要高于公平锁的性能。

读-写锁

ReentrantReadWriteLock:
- 可以选择非公平还是公平锁
- 如果这个锁由读线程持有,而另一个线程请求写入锁,那么其他线程都不能获得读取锁
- 写线程降级为读线程是可以的,但从读线程升级为写线程是不可以的,防止死锁

性能:
分别用ReentrantLock和ReadWriteLock来封装ArrayList的吞吐量,在线程数量大于4的时候,后者的吞吐量大约是前者的3倍左右。

第14章 构建自定义的同步工具

条件队列

条件谓词:put方法的条件谓词是“缓存不满”,take方法的条件谓词是“缓存不为空”
过早唤醒:wait方法的返回并不意味着线程正在等待的条件谓词已经变成真的了
当使用条件等待时(例如Object.wait或Condition.await):
- 通常都有一个条件谓词——包括一些对象状态的测试,线程在执行前必须首先通过这些测试
- 在调用wait之前测试条件谓词,并且从wait中返回时再次进行测试
- 在一个循环中调用wait
- 确保使用与条件队列相关的锁来保护构成条件谓词的各个状态变量
- 当调用wait、notify或notifyAll等方法时,一定要持有与队列相关的锁
- 在检查条件谓词之后以及开始执行相应的操作之前,不要释放锁

通知:优先选择notifyAll
同时满足以下两个条件,才能用单一的notify而是notifyAll:
- 所有的等待线程的类型都相同
- 单进单出

显示的Condition对象

使用显式条件变量的有界缓存:

@ThreadSafe
public class ConditionBoundedBuffer<T> {
    protected final Lock lock = new ReentrantLock();
    //条件谓词:notFull (count < items.length)
    private final Condition notFull = lock.newCondition();
    //条件谓词:notEmpty (count > 0)
    private final Condition notEmpty = lock.newCondition();
    @GuardedBy("lock")
    private final T[] items = (T[]) new Object[BUFFER_SIZE];
    @GuardedBy("lock") private int tail, head, count;

    //阻塞并直到: notFull
    public void put(T x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                notFull.await();
            items[tail] = x;
            if (++tail == items.length)
                tail = 0;
            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    //阻塞并直到: notEmpty
    public T take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();
            T x = items[head];
            items[head] = null;
            if (++head == items.length)
                tail = 0;
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }
}
AbstractQueuedSynchronizer

概念:是许多同步类的基类,例如ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock、SynchronousQueue和FutureTask

java.util.concurrent同步器类中的AQS
  • ReentrantLock:同步状态用于保存锁获取操作的次数
  • Semaphore:同步状态用于保存当前可用许可的数量
  • FutureTask:同步状态用来保存任务的状态
  • ReentrantReadWriteLock:使用一个16位的状态来表示写入锁的计数,并且使用了另一个16位的状态来表示读取锁的计数

第15章 原子变量与非阻塞同步机制

原子变量类
  • 标量类:AtomicInteger、AtomicLong、AtomicBoolean、AtomicReference
  • 更新器类
  • 数组类
  • 复合变量类

性能比较:在中低程度的竞争下,原子变量能提供更高的可伸缩性,而在高强度的竞争下,锁能更有效地避免竞争。

非阻塞算法

概念:如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败或挂起,那么这种算法就被称为非阻塞算法。
实现的技巧:将执行原子修改的范围缩小到单个变量上。

第16章 Java内存模型

**简介:**Java内存模型是通过各种操作来定义的,包括对变量的读/写操作,监视器的加锁和释放操作,以及线程的启动和合并操作,JMM为程序中所有的操作定义了一个偏序关系,称之为Happen-Before。

发布

不安全的发布:当缺少Happen-Before关系时,就可能出现重排序问题,导致在没有充分同步的情况下发布一个对象会导致另一个线程看一个只被部分构造的对象。

线程安全的延迟初始化:

@ThreadSafe
public class SafeLazyInitialization {
    private static Resource resource;

    public synchronized static Resource getInstance() {
        if (resource == null) 
            resource = new Resource();
        return resource;

    }
}

双重检查加锁:不要这么做!!!

@NotThreadSafe
public class DoubleCheckLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckLocking.class) {
                if (resource == null) {
                    resource =  new Resource();
                }
            }
        }
        return resource;
    }
}
OpenClaw 多代理协同工作模式配置指南 OpenClaw 采用。 阅读详情

相关推荐

海康工业相机 Could not find module MvCameraControl.dll(已解决)

【代码】海康摄像机 Could not find module MvCameraControl.dll(已解决)

hmbbpdx的博客 2224

为什么final修饰符是初始化安全的?

看了java并发编程实战,有很多困惑。书中没有讲明白final域能确保初始化过程的安全的。 首先我们来看下创建对象的时候。 User user=new User(); 看过JVM都知道,这其中包含了几步步。 1.检测类是否被加载,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载...

小炫指剑大厂 823

COMSOL仿真分析高压直流GIS/GIL绝缘性能优化

高压直流气体绝缘设备(GIS/GIL)的绝缘性能是保障电网可靠运行的关键。通过COMSOL Multiphysics多物理场仿真,可以深入分析气固界面电场分布与电荷积聚机理。该技术结合静电场、热场和电荷传输耦合计算,能准确模拟温度梯度对SF6气体与环氧树脂界面特性的影响。工程实践中,这类仿真可优化导体结构设计、改进绝缘材料配方,并建立电场-温度关联预警模型。特别是在80℃高温工况下,仿真显示界面电荷密度会显著增加23%,这对设备安全运行具有重要指导价值。

weixin_32075843的博客 192

Java中final修饰符的初始化安全性的理解

今天看《Java并发编程实战》看到安全发布的问题中final修饰符的作用,一时半会没有看明白,查了一些资料才懂了一些深层次的原因,所以做一些记录。

FrankLee的博客 4130

Unity3d 编译发布到安卓平台时出现的问题集

环境搭建好了,android SDK也有了,但导出的时候提示Error building Player: Win32Exception: ApplicationName='java.exe'....... 国内好像没看到解决方法。在Unity3d的论坛里面看到一个解决方法,把C:\windows\system32\java.exe复制到C:\Windows\SysWOW64里面,我这里就解决

erictang01的专栏 1773

高等数学/概率论/数理统计/线性代数/离散数学面试-核心概念-问题理解

特征值与特征向量是线性代数中的概念,它们与线性变换有关。在线性变换中,如果存在非零向量 v ,使得当该向量通过变换后,其方向不变,只是长度发生了变化,那么这个向量 v 就是特征向量。而这个长度变化的比例因子,即变换前后向量长度的比值,称为特征值。数学公式表示:通俗易懂的解释:想象一下,你有一个可以伸缩的橡皮筋,这个橡皮筋可以代表一个向量。现在,你有一个特殊的机器,它可以改变橡皮筋的形状,但不会改变它延伸的方向。当你把橡皮筋放入机器中,机器会拉伸或压缩橡皮筋,但橡皮筋的方向保持不变。

m0_64198455的博客 2293

Java并发编程实战(学习笔记二 第三章 对象的共享)

(转自:https://blog.youkuaiyun.com/ahaha413525642/article/details/76574351 侵删)本章将介绍如何共享和发布对象,从而使它们嫩能够安全地由多个线程同时访问。3.1 可见性(Visibility)通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至不可能。为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制。下面的 N...

weixin_41704428的博客 861

【AMD显卡在WIndow10/11部署带GPU支持的深度学习环境(Pytorch-DirectML篇)】

这篇是之前Tensorflow-DirectML的姊妹篇,如果对TF感兴趣的可以搜索我的博文。 首先我们丢一个官网地址,但是官网那个会误导新人如果你按那个操作的话。 https://docs.microsoft.com/en-us/windows/ai/directml/gpu-pytorch-windows 这里用我的方法操作: 首先声明一下,因为我的显卡是AMD RX6600,不带XT(性能和RTX3060 12G版本半斤八两),所以目前没有最新的WSL2驱动,如果有了的话欢迎告知我,所以我这里就.

weixin_44029053的博客 2万+

java的中断机制_关于java的中断机制(interrupt)

参考资料:http://www.infoq.com/cn/articles/java-interrupt-mechanismJava编程并发实战当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务。Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。一、中断的基本概念Jav...

weixin_29570673的博客 473

从Simulink仿真到DSP28335真机部署:PID闭环控制快速移植指南

本文详细介绍了如何将Simulink中的PID闭环控制算法快速移植到DSP28335嵌入式平台。通过模型与代码映射、浮点与定点数选择、定时器中断配置、物理输出实现以及调试技巧五个关键步骤,帮助工程师高效完成从仿真到真机部署的全过程,特别适合需要实现精确控制的嵌入式开发者。

weixin_42521843的博客 363

通信原理 | 随机数仿真 | 均匀、正态、双高斯、瑞利、莱斯、对数正态、nakagami、Suzuki分布的随机数仿真(matlab)

信道建模在通信系统设计和分析中扮演着至关重要的角色。它指的是使用数学和物理模型来描述和模拟无线或有线通信路径中的信号传播特性。

若北辰 1988

Java并发编程实战读书笔记——第二章线程安全性

645132

MADE_哒哒 488

python-pandapower电力系统潮流计算(算例8:ieee33节点潮流计算))

python-pandapower电力系统潮流计算(算例8:ieee33节点潮流计算))

总裁余(余登武)博客 5034

《java并发编程实战》读书笔记——线程池

饱和策略 1.“终止”策略,默认策略: 该策略将抛出 RejectedExecutionException。 当无法放入队列中时,抛弃该任务。 2.“调用者运行”策略: 当任务队列满时。 将下一个提交上来的任务,交给调用ExecutorService来执行任务的主线程来执行,而不再通过ExecutorService线程池来执行这个任务 由于执行任务需要一定的时间,因此

Great_Smile的专栏 867

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

《Java并发编程实战》读书笔记——线程池、Callable、Future、FutureTask

1、Executor和ExecutorService    基于生产者——消费者模式,提交任务的线程是生产者,执行的是消费者。public interface Executor { void execute(Runnable command); }    为了解决执行服务的生命周期问题,有了ExecutorService接口,添加了一些用于生命周期管理的方法。线程池有RUNNING、SHUTDO...

weixin_39420024的博客 316

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

《Java并发编程实战》第八章 线程池的使用 读书笔记

一、在任务与执行策略之间的隐性解耦 有些类型的任务需要明确地指定执行策略,包括: . 依赖性任务。依赖关系对执行策略造成约束,需要注意活跃性问题。要求线程池足够大,确保任务都能放入。 . 使用线程封闭机制的任务。需要串行执行。 . 对响应时间敏感的任务。 . 使用ThreadLocal的任务。 1. 线程饥饿死锁 线程池中如果所有正在执行任务的线程都由于等待其他仍处于工作

Android 2134

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java并发编程实战读书笔记(1)线程安全性

Java并发编程实战笔记(1) 线程安全性 1.线程安全 2.竞价条件 定义:由于不恰当的执行执行时序而出现不正确的执行结果 3.加锁机制 竞价条件 竞价条件 六级标题

老何的自我救赎 248

【读书笔记】《Java并发编程实战》第二章 线程安全性

线程安全性知识梳理线程安全性竞态条件数据竞争与竞态条件勿混淆复合操作加锁机制内置锁重入用锁来保护状态活跃性与性能 线程安全性 要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问管理。 竞态条件 当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。 最常见的竞态条件就是“先检查后执行”操作,另一种竞态条件是“读取-修改-写入”。 数据竞争与竞态条件勿混淆 数据竞争是指,如果在访问共享的非final类型的域时没有采用同步来进行协同,那么就会出现数据竞争。

GuYan的博客 547

Java并发编程实战读书笔记——第二章 线程安全性

第二章 线程安全性 如何通过同步来避免多个线程在同一时刻访问相同的数据。 2.1 什么是线程安全性 修复多线程问题的三种方式: a. 不在线程之间共享该状态变量 b. 将状态变量修改为不可变的变量 c. 在访问状态变量时使用同步 正确的编程方法:首先使代码正确运行,然后再提高代码的速度。即使如此,最好也只是当性能测试结果和应用需求告诉你必须提高性能,以及测量结果表明这种优化在实际...

AhahaGe 374

读书笔记 JAVA 并发编程实战 第二章 线程安全

编写线程安全的代码,核心是对于状态的访问操作进行管理。共享的和可变的状态的访问。 非正式意义上来说,对象的状态是指存储在状态变量中的数据(实例或静态域)中的数据。对象的状态可能包含其他依赖对象的域。(HashMap 状态也存储在Map.Entry中) “共享”意味着变量可以由多个线程同时访问了,而“可变”意味着变量的值在其生命周期内可以发生改变。一个对象是否需要是线程安全的...

ansu1955的博客 181

【读书笔记】《Java并发编程实战》第八章 线程池的使用

线程池知识梳理1.线程饥饿死锁2.设置线程池的大小 1.线程饥饿死锁 在线程池中,如果任务依赖于其他任务,那么可能导致死锁。在单线程的Executor中,第二个任务停留在工作队列中,等待第一个任务的完成,之后到第二个任务开始执行,而第一个任务又需要第二个任务完成的结果,因此这样就导致死锁。只要线程池中的任务需要无限期地等待一些必须由池中其它任务才能提供的资源或条件,例如某个任务等待另一个任务的返回值或执行结果,除非线程池足够大,否则将发生线程饥饿死锁。例如: //在单线程Executor中任务发生死锁(不要

GuYan的博客 426

《Java并发编程实战》读书笔记二:构建线程安全

一、用组合来实现线性安全1.设计线程安全的类设计线程安全类的三个基本要素: 1. 找出构成对象状态的所有变量 2. 找出约束状态变量的不变性条件 3. 建立对象状态的并发访问管理策略要分析对象的状态,首先从对象的域开始。如果对象所有的域都是基本类型的变量,那么这些域将构成对象的全部状态;如果对象的域中引用了其他对象,那么该对象的状态将包含被引用的对象的域。2.实例封闭当一个对象被封装到另一个对

XXX 1130

读书笔记——java并发编程实战-第二章 线程安全性

存在线程安全问题的前提: 该变量可被修改 该变量被多个线程访问 当多个线程访问同一个可变状态的变量时,没有进行合适的同步,那么程序就会出现错误。共有三种方法解决该问题: 不在线程之间共享该状态变量 将状态变量修改为不可变的变量 在访问时,使用同步 一、什么是线程安全性? 线程安全性:当多个线程访问某个类时,这个类始都能出现正确的行为,那么我们就称这个类是线程安全的。 无状态的对象一定是线程安全的 (有状态与无状态:有状态就是有存储数据的功能的类。无状态就是该类中的属性不存储数据) 二、原子性 1.竞态条

java懒惰工程师 1322

Java并发编程实战读书笔记——第八章 线程池的使用

8.1 在任务与执行策略之间的隐性耦合 有些类型的任务需要明确地指定执行策略,包括: 1.依赖性任务:避免产生活跃性问题 2.使用线程封闭机制的任务:任务要求其执行所在的Executor是单线程的。 3.对响应时间敏感的任务 4.使用ThreadLocal的任务 线程池的线程中不应该使用ThreadLocal在任务之间传递值。只有当线程本地值的生命周期受限于任务的生命周...

AhahaGe 387

《Java并发编程实战》读书笔记0_第二章:线程安全性

本文章为读书笔记,字全是手敲的,整理书中知识点和自己的观点 要编写线程安全的代码其核心在于对状态访问操作进行管理,特别是对共享的(Shared)和可变的(Mutable)状态的访问。 “共享”意味着变量可以有多个线程同时访问,而“可变”则意味着变量的值在其生命周期内可以发生变化。 一个对象是否需要是线程安全的,取决于它是否被多个线程访问。这指的是在程序中访问对象的方式,而不是带向要是想的功能。...

啤酒就辣条 216

《Java并发编程实战》第二章 线程安全性 读书笔记

一、什么是线程安全性 编写线程安全的代码 核心在于要对状态访问操作进行管理。 共享,可变的状态的访问 - 前者表示多个线程访问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性。某个类的行为与其规范完全一致。 多个线程同时操作共享的变量,造成线程安全性问题。 * 编写线程安全性代码的三种方法: 不在线程之间共享该状态变量 将状态变量修改为不可变的变量 在访问

Android 1948
上一篇: JAVA最全面试题答案整理
下一篇: Spring技术内幕——读书笔记
刘五分
博客等级 码龄10年 15粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值