head first java ( 15 章 )

网络作业内容很容易, 因为所有的网络运作底层细节已经由java.net函数库处理了. 然后使用 串流(上一章内容)

来接收消息, java 串流一般不管上游文件来自哪里, 网络还是本地的txt文件

client 端

- 连接,传送,接收

  1. 如果建立客户端与服务器之间的初始连接

  2. 传送消息到服务器

  3. 如何接收来自服务器的消息

 image

  1. 建立 socket 连接 ( 要知道服务器 ip 和 port )

  Socket chatSocket = new Socket(“192.168.0.99”, 5000);

  注: 不同程序不能共享一个端口

  -- 从服务器读内容

  InputStreamReader stream = new InputStreamReader(chatSocket.getInputStream()); ( 中间层 )

  BufferReader reader = new BufferReader(stream); // 这的 stream 来自于中间层

  String message = reader.readLine();

  image

  -- 写内容到服务器(也要先建立socket连接)

  image 

  image

- 例子

Client

Server 端

-- 监听端口

image

-- client 请求连接

image

-- 建立连接

image

- 例子

Server


注: 以上 Server 与 Client 都要一起同时使用.

目前的程序是, 当处理一个客户端请求时没有办法处理别的请求, 怎么办呢?

可以通过线程来满足需要

引入线程, 线程是独立的线程, 它代表独立的执行空间, 当你需要启动新的线程时就建立Thread的实例


进入线程的世界

image

要记得, java也只是个在底层操作系统上执行的进程,一旦轮到JAVA执行的时候,JAVA虚拟机实际上会执行什么?

哪个字节码会被执行? 答案是目前执行空间最上面的会被执行,在100个毫秒内,目前执行程序代码会被切换到不同空间上

的不同方法。 -- 线程要记录的一项事务时目前线程执行空间做到哪里。

image

- 如何启动新的线程

image

image

image

注: 每个 Thread 需要一个任务来执行, 一个可以放在执行空间的任务

对Thread而言, 它是个工人,而 Runnable 就是这个工人的工作。( Runnable带有会放在执行空间的第一项方法 run() )

- 新建立线程的 3 个状态

  image

  通常线程会在可执行与执行中两种状态中来回交替,线程有可能会暂时被挡住,例如调用某个被锁住的对象的方法,此时

  线程就的等到锁住对象的线程放开这个对象才能继续执行,这类型的条件会导致线程暂时失效。(由线程调度器控制)

- 线程调度器

  线程调度器会决定哪个线程从等待状态中被挑出来运行,以及何时把哪个线程送回等待被执行的状态。你无法控制调度器

  注: 一旦启动线程, 程序的顺序就不受控制,并不是线程执行完了才执行线程下边的语句,记住,它们是独立的执行空间

  一个线程只能执行一项任务. 一旦开始执行,就不能再接其他任务。

- Thread.sleep(2000)

  如果想要确保其他的线程有机会执行的话,就线程放进睡眠状态。当线程醒来时,它会进入可执行状态等待被调度器挑出来执行。

  try {

        Thread.sleep(2000);

  } catch ( InterruptedException ex) {

      ex.printStackTrace();

  }

  千万不要依靠这种机制来精确地控制执行时机. ( 例如电影中的独白与动作同步 )

- 线程的缺点

  线程会产生并发性的问题( 两个或两个以上的线程存取单一对象的数据. 也就是说 两个或两个以上不同执行空间上的方法都在

  堆上对同一个对象执行 getter 或 setter

  引入 “锁” 原子性

  synchronized的方法,只能被单一线程调用 synchronized , 例如 private synchronized

  锁不是配在方法上的,而是配在对象上,如果对象有两个同步化方法时(即两个synchronized方法),要么都可以进去,要么都不可以。

  同步化方法的目标是要保护重要的数据,但是要记住,你锁住的不是数据而是存取数据的方法。

  为什么锁的不是方法是对象呢, 其主要目的是锁住实例变量, 假如有两个方法非别是a,b, 都对实例变量age进行访问, 判断age的大小以进行操作, 如果只锁住一个函数, 那么其他的函数修改了age 的值, 那么程序就会有问题, 所以要锁住对象.

  每个 java 对象都有一个锁,类也有锁,这表示3个Dog对象在堆上,那么实际有4个锁

  所以线程在开始执行并遇上有同步化的方法时候会发生什么事? 线程会认知到它需要对象的钥匙才能进入该方法,它会取得钥匙

  这是由Java虚拟机来处理的, 没有存取对象锁得API, 如果可以拿到钥匙才会进入方法.

  注: 同步化方法越少越好, 而且范围越小越好, 只要考虑原子性问题的时候, 才考虑同步化

  同步化一定要注意,会引起“死锁”

  image

  foo 的到了对象A的锁,同时想申请对象B的锁,同时 bar得到了对象B的锁,想申请对象A的锁,那么就只有等待。。。

 

 

原文地址:https://www.cnblogs.com/moveofgod/p/3026525.html