IT学习笔记(一)(持续更新)

一、java并发

1、多线程执行代码即CPU通过给每个线程分配CPU时间片来实现这个机制;时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,时间片一般是几十毫秒。

2、任务从保存到再加载的过程是一次上下文切换,上下文切换会影响多线程的执行速度。

3、并发执行的开销主要是线程的创建和上下文切换。减少上下文切换的方法有:无锁并发编程、CAS算法、使用最少线程和使用协程。

4、避免死锁的常用办法:

(1)   避免一个线程同时获取多个锁;

(2)   避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源;

(3)   尝试使用定时锁,使用lock.tryLock(timeout)来替代内部锁机制;

(4)   对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

5、线程之间的通信机制有两种:共享内存和消息传递。在共享内存的并发模型中,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信;在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过发送消息显式进行通信。

6、Java中,所有实例域、静态域和数组元素都存储在堆内存中,堆内存在线程间共享。局部变量、方法定义参数和异常处理器参数不会在线程间共享,不会有内存可见性问题,也不会受内存模型的影响。

7、线程:现代操作系统调度的最小单元,一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。

8、一个java程序的运行不仅仅是main()方法的运行,而是main线程和多个其他线程的同时运行。

9、在java线程中,通过一个整型变量priority来控制优先级,优先级的范围从1-10,在线程构建的时候可通过setPriority(int)方法来修改优先级,默认优先级是5,优先级高的线程分配时间片的数量要多于优先级低的线程。针对频繁阻塞(休眠或I/O操作)的线程需要设置较高的优先级,而偏重计算(需要较多CPU时间或偏运算)的线程则设置较低的优先级,确保处理器不会被占用。

10、Java线程在运行的生命周期中有6种不同的状态,在给定的一个时刻,线程只能处于其中一个状态,随着代码的执行在不同的状态之间进行切换。

11、 线程的suspend()方法在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题;stop()方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。因此,suspend()、resume()和stop()方法被标注为不建议使用的过期方法。其中暂停(suspend())和恢复(resume())操作可通过等待/通知机制来代替。

12、通过标志位或者中断(interrupt())操作的方式能够使线程在终止时有机会去清理资源,而不会武断的将线程停止,因此这种终止线程的做法显得更加安全和优雅。

13、关键字volatile可以用来修饰字段(成员变量),告知程序任何对该变量的访问均需要从共享内存中获取,而对他的改变必须同步刷新回共享内存,它能够保证所有线程对变量的可视性。

14、关键字synchronized可以修饰方法或者以同步块的形式进行使用,它主要确保多个线程在同一个时刻,只有一个线程处于方法或者同步块中,保证了线程对变量访问的可视性和排他性。

15、任意一个对象都拥有自己的监视器,当这个对象由同步块或者这个对象的同步方法调用时,执行方法的线程必须先获取到该对象的监视器才能进入同步块或者同步方法,而没有获取到监视器(执行该方法)的线程将会被阻塞在同步块和同步方法的入口处,进入BLOCKED状态。

16、Java通过内置的等待/通知机制能够很好地解决难以确保及时性和难以降低开销的问题,而且等待/通知的相关方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类java.lang.Object上。

17、调用wait()、notify()以及notifyAll()时需要注意的细节,如下:

    1)使用wait()、notify()和notifyAll()时需要先对调用对象加锁。

    2)调用wait()方法后,线程状态由RUNNING变为WAITING,并将当前线程放置到对象的等待队列。

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

    4)notify()方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而notifyAll()方法则是将等待队列中所有的线程全部移到同步队列,被移动的线程状态由WAITING变为BLOCKED。

    5)从wait()方法返回的前提是获得了调用对象的锁。

    从上述细节中可以看到,等待/通知机制依托于同步机制,其目的就是确保等待线程从wait()方法返回时能够感知到通知线程对变量做出的修改。

18、管道输入/输出流和普通的文件输入/输出流或者网络输入/输出流不同之处在于,它主要用于线程之间的数据传输,而传输的媒介为内存。对于Piped类型的流,必须先要进行绑定,也就是调用connect()方法,如果没有将输入/输出流绑定起来,对于该流的访问将会抛出异常。

19、如果一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才从thread.join()返回。线程Thread除了提供join()方法之外,还提供了join(long millis)和join(longmillis,intnanos)两个具备超时特性的方法。这两个超时方法表示,如果线程thread在给定的超时时间里没有终止,那么将会从该超时方法中返回。

20、线程池的本质就是使用了一个线程安全的工作队列连接工作者线程和客户端线程,客户端线程将任务放入工作队列后便返回,而工作者线程则不断地从工作队列上取出工作并执行。当工作队列为空时,所有的工作者线程均等待在工作队列上,当有客户端提交了一个任务之后会通知任意一个工作者线程,随着大量的任务被提交,更多的工作者线程会被唤醒。

21、锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(但有些锁可允许多个线程并发的访问共享资源,比如读写锁)。之前,java程序通常靠synchronized关键字来实现锁功能,在Java SE5之后,并发包新增了Lock接口来实现锁的功能。它在使用时需要显式的获取和释放锁。同时拥有锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。

    ConcurrentHashMap的锁分段技术,即将数据分成一段一段地存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。它由Segment数组结构和HashEntry数组结构组成,而Segment是一种可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。ConcurrentHashMap包含3种操作,即get操作、put操作和size操作。

二、WebSocket

1、概念:WebSocket是一种在单个 TCP 连接上进行全双工通讯的协议。是一个持久化的协议,相对于HTTP这种非持久的协议来说。

    在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

     浏览器通过 JavaScript 向服务器发出建立WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

    当你获取 Web Socket 连接后,你可以通过send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

创建实例化对象,参数是需要连接的服务端的地址,同http协议使用http://开头一样,WebSocket协议的URL使用ws://开头,另外安全的WebSocket协议使用wss://开头。例如:

    var wsUri="ws://echo.websocket.org/";

    websocket = new WebSocket(wsUri);

3、WebSocket对象一共支持四个消息onopen, onmessage, onclose和onerror。所有的操作都是采用消息的方式触发的,这样就不会阻塞UI,使得UI有更快的响应时间,得到更好的用户体验。

    (1)当Browser和WebSocketServer连接成功后,会触发onopen消息。例如:websocket.onopen = function(evt) {};

    (2)如果连接失败,发送、接收数据失败或者处理数据出现错误,browser会触发onerror消息。例如websocket.onerror= function(evt) { };

    (3)当Browser接收到WebSocketServer发送过来的数据时,就会触发onmessage消息,参数evt中包含server传输过来的数据。例如:websocket.onmessage = function(evt) { };

    (4)当Browser接收到WebSocketServer端发送的关闭连接请求时,就会触发onclose消息。例如:websocket.onclose= function(evt) { }。

4、WebSocket和Http协议一样都属于应用层的协议,WebSocket在建立握手连接时,数据是通过http协议传输的,但是在建立连接之后,真正的数据传输阶段是不需要http协议参与的。

5、WebSocket的优点:

    1)、服务器与客户端之间交换的标头信息很小,大概只有2字节;

    2)、客户端与服务器都可以主动传送数据给对方;

    3)、不用频率创建TCP请求及销毁请求,减少网络带宽资源的占用,同时也节省服务器资源。

6、WebScoket协议中,数据以帧序列的形式传输。考虑到数据安全性,客户端向服务器传输的数据帧必须进行掩码处理。服务器若接收到未经过掩码处理的数据帧,则必须主动关闭连接。而服务器向客户端传输的数据帧一定不能进行掩码处理。客户端若接收到经过掩码处理的数据帧,则必须主动关闭连接。针对上情况,发现错误的一方可向对方发送close帧(状态码是1002,表示协议错误),以关闭连接。

7、HTTP协议是无状态的,每次请求(request)都要由客户端(如浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据。

    轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。明显地,这种方法会导致过多不必要的请求,浪费流量和服务器资源。长轮询改进了上述的轮询技术,减小了无用的请求。它会为某些数据设定过期时间,当数据过期后才会向服务端发送请求;这种机制适合数据的改动不是特别频繁的情况。

     流技术通常是指客户端使用一个隐藏的窗口与服务端建立一个HTTP长连接,服务端会不断更新连接状态以保持HTTP长连接存活;这样的话,服务端就可以通过这条长连接主动将数据发送给客户端;流技术在大并发环境下,可能会考验到服务端的性能。

8、Java+WebSocket构建动态Web应用

    1)注解@ServerEndpoint是类级别的注解。告诉java平台它注解的类实际上要成为一个WebSocket端点。此注解的唯一强制参数是相对URL。例如:@ServerEndpoint(“/端点名”)

    2)注解@OnOpen,用于注解式端点的方法,指示当此端点建立新的连接时调用此方法。

    3)注解@OnMessage,此注解能够在连接建立后处理一些或者所有的入站消息。连接上的消息将以3种基本形式抵达:文本消息、二进制消息或Pong消息。

    注解@OnError,可以处理入站消息时发生的任何错误。注解@OnClose可以用来注解多种不同类型的方法来处理关闭事件。

猜你喜欢

转载自blog.csdn.net/xudasong123/article/details/79789946