线程

Invoke and BeginInvoke

和自甴很熟 提交于 2020-02-29 17:54:46
在 Invoke 或者 BeginInvoke 的使用中无一例外地使用了委托 Delegate ,至于委托的本质请参考我的另一随笔: 对 .net 事件的看法 。 一、为什么 Control 类提供了 Invoke 和 BeginInvoke 机制? 关于这个问题的最主要的原因已经是 dotnet 程序员众所周知的,我在此费点笔墨再次记录到自己的日志,以便日后提醒一下自己。 1 、 windows 程序消息机制 Windows GUI 程序是基于消息机制的,有个主线程维护着一个消息泵。这个消息泵让 windows 程序生生不息。 Windows GUI 程序的消息循环 Windows 程序有个消息队列,窗体上的所有消息是这个队列里面消息的最主要来源。这里的 while 循环使用了 GetMessage ()这个方法,这是个阻塞方法,也就是队列为空时方法就会被阻塞,从而这个 while 循环停止运动,这避免了一个程序把 cpu 无缘无故地耗尽,让其它程序难以得到响应。当然在某些需要 cpu 最大限度运动的程序里面就可以使用另外的方法,例如某些 3d 游戏或者及时战略游戏中,一般会使用 PeekMessage ()这个方法,它不会被 windows 阻塞,从而保证整个游戏的流畅和比较高的帧速。 这个主线程维护着整个窗体以及上面的子控件。当它得到一个消息,就会调用

数据库和缓存双写的一致性问题

本秂侑毒 提交于 2020-02-29 17:30:31
首先,数据库与缓存双写不可能做到强一致性,只能做到最终一致性。如果项目要求是强一致性的,那么不能使用缓存。 从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。因此,接下来讨论的思路不依赖于给缓存设置过期时间这个方案。 方案一:先更新缓存,再更新数据库 这种方式肯定不行的,缓存更新成功,数据库更新失败,怎么办? 方案二:先更新数据库,再更新缓存 有一致性问题。如果线程A先更新了数据库,然后线程B更新了数据库,接下来线程B更新了缓存,最后线程A更新了缓存。按道理线程A更新缓存应该比线程B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存,这就导致了脏数据,因此不考虑。 方案三:先删缓存,再更新数据库 也会导致不一致。比如请求A进行写操作,删除了缓存,请求B查询发现缓存不存在,去数据库查询得到旧值并将旧值写入缓存,最后请求A将新值写入数据库。上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。 方案四:先更新数据库,再删除缓存 老外提出了一个缓存更新套路,名为 《Cache-Aside pattern》

JAVA多线程_线程安全问题

不想你离开。 提交于 2020-02-29 17:28:16
当多条语句(线程)在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。这样就是线程的安全问题。 解决线程安全的方式有两种: 1.synchronized同步机制 2.Lock锁 一、synchronized同步机制 1.同步代码块 同步代码块的意思就是将需要操作的共享数据的代码段用synchronized同步执行 synchronized (对象){ // 需要被同步的代码; } 2.同步方法 synchronized可以放在方法声明中,表示整个方法为同步方法。 public synchronized void show (String name){ …. } 可以将此方法放入需要多线程执行的run()方法中调用 二、Lock锁 从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。 锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。 class A{ private final ReentrantLock lock = new ReenTrantLock(); public void main(){ lock.lock(); try{ //保证线程安全的代码; }finally{

1、JUC系列之---线程基础

∥☆過路亽.° 提交于 2020-02-29 17:22:03
一、多线程概述 1、进程:正在进行中的程序 2、线程:就是进程中一个负责程序执行的控制单元(执行路径) 一个进程中,可以有多个执行路径,即多线程 一个进程中,至少有一个执行路径。 (多线程其实就是多个线程中的快速切换) 二、多线程的创建方式①--继承Thread类 继承Thread类,重写run方法 1、JVM创建的主线程的任务都定义在了主函数中 2、Thread类中的run方法就是封装自定义线程任务的函数,即run方法相当于一个main方法 package com.lee.juc; public class ThreadDemo_01 { public static void main(String[] args) { Demo demo1 = new Demo("张三"); Demo demo2 = new Demo("LeeSi"); demo1.start(); demo2.start(); System.out.println("=======结束========"); } } class Demo extends Thread{ private String name; @Override public void run() { for(int i=0;i<10;i++) { System.out.println(name+"====>"+i); } } public

C#中跨线程操作控件 --- InvokeRequired 属性 与Invoke方法

≡放荡痞女 提交于 2020-02-29 17:04:02
在设计中为了让界面与逻辑分离,我的做法是使用事件,界面只要响应事件来处理界面的显示就可以了。而事件在逻辑处理中可能由不同的线程引发,这些事件的响应方法在修改页面中的控件内容时便会引发一个异常。 这时就用到了Control.InvokeRequired属性与Invoke方法。 获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用Invoke方法,因为调用方位于创建控件所在的线程以外的线程中。 如果控件的handle是在与调用线程不同的线程中创建的(说明您必须通过invoke方法对控件进行调用),则为true,否者为false。 Windows窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个invoke方法来将调用封送到适当的线程。该属性可用于确定是否必须调用invoke方法,当不知道什么线程拥有控件时这很有用。 下面来说下具体的用法: 首先定义一个委托,与这个事件处理很熟的签名一样委托,当然直接使用该事件的委托也是可以的,如: private delegate void DoLog(string msg); 然后判断这个属性的值来决定是否要调用invoke函数: if (this.InvokeRequired) { DoLog doLog = new DoLog(Log); this.Invoke(doLog,

java内存模型规范学习总结

ぃ、小莉子 提交于 2020-02-29 16:29:17
java内存模型 复习jdk1.7虚拟机规范 了解java内存模型,需要我们对计算机硬件体系有一个基本掌握,要知道计算机里面的内存、高速缓冲、处理器、内存一致协议这些概念。 硬件系统内存模型 现代计算机为了解决处理器与存储设备之间性能冲突,引入了高速缓存,高速缓存读写速度接近处理器运算速度,为处理器单独使用。将运算需要使用到的数据复制到缓存种,让运算能快速进行,当运算结束后再从缓存同步回内存之中,这样处理器就不需要等待内存的读写了。 而在多处理器系统中,就涉及到 缓存一致性 问题,每个处理器都有自己的高速缓存,而它们又共享同一主内存。 内存模型:在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程。 java内存模型 不同的物理架构可以拥有不一样的内存模型,而java内存模型就是为了解决各种物理机上内存访问差异而产生的,以实现让java程序在各种平台下达到一致的内存访问效果。 java内存模型的目标,是定义程序中各个变量的访问规则,即在虚拟机中将变量的存储到内存和从内存中取出变量这样的底层细节。 java内存模型规定所有的变量都存储在主内存。 线程拥有自己的工 作内存,保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作必须在工作内存中完成,不能直接操作主内存。 不同的线程不能直接访问对方的工作内存中变量,线程间变量值传递必须通过主内存来完成。

volatile的原理分析

安稳与你 提交于 2020-02-29 16:16:49
前言:Volatile作为一个多线程开发中的强有力的轻量级的线程协助工具,在实际编程中随处可见,它比synchronized更加轻量和方便,消耗的资源更少,了解Volatile对后面了解多线程有很重要的意义,本篇博客我们就来探究如果在一个字段上加上Volatile,那么它实际上到底起了什么作用?以及是怎么工作的? 本篇博客的目录: 一:工作内存和主内存 二:volatile的两大作用 三:volatile一定是线程安全的吗? 四:Volatile的局限性和适用场景 五:总结 正文开始 一:工作内存和主内存 1.1:它们具有的特点 ①主内存是所有变量的存储地方,这包括所有你看到的变量包括实例变量、静态字段、数组对象的元素 ②工作内存是线程私有的,所有的线程在操作变量(读取或者赋值)的时候都必须在工作内存中完成,而不能在主内存中进行 ③不同的线程之间无法访问对方的工作内存中的变量,线程之间传递值需要在工作内存中进 行 1.2: 图示 该图主要模拟了5个线程的工作内存和主内存之间的交互,可以看出不同线程之间是不可以进行变量交换的,它们公用一个主内存,所有的变量传递都在主内存中进行完成 二:volatile的两大作用 2.1:线程可见性 这里的可见性是指若一个变量被Volatile修饰,那么假如A线程对其进行了修改操作,那么其他线程都会立刻拿到修改后的值

Java线程编程(基础知识点)

ε祈祈猫儿з 提交于 2020-02-29 15:49:37
进程与线程概念 进程 :一个或多个程序,在一组数据上的一次执行过程,被称为进程。每一个进程有一套独立的数据。 线程 :线程是“轻量级”进程;线程是由进程创建的,但线程不再另外申请计算机资源,所以,线程要比进程“轻”。就是说,线程不需要像进程那样拥有庞大的资源表,也不需要像进程那样对资源进行严格的管理;线程所i使用的资源都是由进程申请的;多个线程的状态切换也比进程更简单、更省时;线程也可以再生成新的线程,称为子线程。 进程是计算机资源的竞争者。 打开任务管理器可以发现,很多的任务“同时”运行。我们可以这样理解,每个任务都是一个进程,而这个进程是可以是多个线程完成的。 进程的管理是需要消耗计算机时间片段和计算机内存资源的。 进程的管理与调度 多道程序的调度使得每一个程序的执行(占有CPU)变得很随机。 为了更好地理解进程,我们可以将进程分为5种不同的状态:创建态、就绪态、运行态、阻塞态和销毁态。 注 : 1.进程创建后并不是立刻进入运行态; 2.而是先进入就绪态,和其他进程竞争CPU(一个CPU一次只能执行一条机器语言); 3.就绪态存在一个进程队列; 4.只有在就绪态队列中的进程才有资格竞争CPU; 5.就绪态进程除了CPU外,不需要等待其他计算机资源; 6.阻塞态往往有多个阻塞队列; 7.阻塞态的进程只能由运行态的进程唤醒; 8.被唤醒后不是立刻进入运行态的,而是先进入就绪态

线程间的互斥(synchronized )

℡╲_俬逩灬. 提交于 2020-02-29 14:34:01
线程互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。 /** * 线程间的互斥 * @author MrRock * */ public class TraditionalThreadSynchronized { public static void main(String[] args) { new TraditionalThreadSynchronized().init(); } void init(){ final Outputer out = new Outputer(); //线程1 new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } out.output1("Tmethod--->AAAAAA"); } } }).start(); //线程2 new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(200); } catch

(多)线程——Thread(三)

吃可爱长大的小学妹 提交于 2020-02-29 13:53:01
Object类是所有类的祖先类。 线程加锁示例 定时器||闹钟 //定时器,闹钟 import java . util . Timer ; import java . util . TimerTask ; public class UserTime { private static class MyTimerTask1 extends TimerTask { @Override public void run ( ) { System . out . println ( "该起床了!" ) ; } } /*private static class MyTimerTask2 extends TimerTask { @Override public void run() { System.out.println("该洗脸了!"); } }*/ /*private static class MyTimerTask3 extends TimerTask { @Override public void run() { System.out.println("该刷牙了!"); } }*/ public static void main ( String [ ] args ) { Timer timer = new Timer ( ) ; timer . schedule ( new