五 多线程:
5.1 Java创建一个线程
1)Thread 类: 线程包含一个可以运行的过程(方法)
Thread 类中包含方法 run
2) 创建一个具体线程, 需要继承于Thread类
3) 覆盖run 方法(就是更新运行过程), 实现用户自己的过程
4) 创建线程实例(一个线程)
5) 使用线程实例的start() 方法启动线程, 启动以后线程会尽快的
去并发执行run()
5.2线程的状态
1 new 新建
2 Runnable 可以运行(就绪)
3 Running 运行(正在运行)
4 Block 阻塞 挂起
5 Dead 死亡c
5.3线程状态管理:
1)让出CPU
Thread.yield() 当前线程让出处理器(离开Running),
使当前线程进入Runnable等待
2)休眠
Thread.sleep(times) 使当前线程从 Running 放弃处理器
进入Block状态, 休眠times毫秒, 再返回到Runnable
如果其他线程打断当前线程的Block(sleep), 就会发生
InterruptedException.
5.4 线程的常用属性
1)线程的优先级 (资源紧张时候, 尽可能优先)
t3.setPriority(Thread.MAX_PRIORITY);
优先级高的线程获得执行的机会多. 机会的多少不能通过代码干预.
默认的优先级是 5
2)后台线程(守护线程, 精灵线程)
t1.setDaemon(true);
Java进程的结束: 当前所有前台线程都结束时, Java进程结束
后台线程, 不管是否结束, 都被停掉!
3) 线程名字
getName()
当前线程
Thread main = Thread.currentThread();
5.5 两种方式创建线程
1)继承Thread类
a 继承Thread类, 覆盖run()方法, 提供并发运程的过程
b 创建这个类的实例
c 使用start() 方法启动线程
2)实现Runnable接口
a 实现Runnable接口,实现run()方法, 提供并发运程的过程
b 创建这个类的实例, 用这个实例作为Thread构造器参数
创建Thread类.
c 使用start() 方法启动线程
class FooThread implements Runnable{
public void run(){
t.join(1000)
…
}
}
Thread t = new Thread(new FooThread());
t.start();
3)使用 内部类/匿名类 创建线程
5.6 Sleep 的打断唤醒
2)同步: 步调一致的处理, 如: 一群人上公交车, “伦敦制”
同步代码块(掌握)
1.什么情况下需要同步
当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
2.同步代码块
使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
多个同步代码块如果使用相同的锁对象(锁对象可以是任意的,Object对象都可以的), 那么他们就是同步的
锁对象不能用匿名对象,因为匿名对象不是同一个对象
3.同步方法(掌握)
使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的
非静态的同步方法的锁对象是this,静态的同步方法的锁对象是该类的字节码对象(类名.class),不是类名.this
4.线程安全问题(掌握)
多线程并发操作同一数据时, 就有可能出现线程安全问题
使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不 要多个线程一起操作
5.死锁(了解)
多线程同步的时候, 如果同步代码嵌套, 使用相同锁, 就有可能出 现死锁(在开发中尽量不要嵌套使用)
6.每个对象都有一个内部锁(Object类已经实现了相关方法),并且该锁有一个内部条件.由该锁来管理那些试图进入synchronized方法的线程,由该锁中的条件来管理那些调用wait的线程
5.8.线程并发安全问题
多个线程并发读写同一个临界资源时候会发生"线程并发安全问题"
常见的临界资源:
多线程共享实例变量
静态公共变量
使用同步代码块解决线程并发安全问题
synchronized(同步监视器){
}
a 同步监视器 是一个任意对象实例. 是一个多个线程之间的互
斥的锁机制. 多个线程要使用同一个"监视器"对象 实现同步互斥
b 常见写法:
synchronized(this){
}
c 如果方法的全部过程需要同步, 可以简单使用 synchronized
修饰方法. 相当于整个方法的 synchronized(this)
d 尽量减少同步范围, 提高并发效率
5.9Java中同步的API
1 StringBuffer 是同步的
synchronized append();
Thread t1 buf.append(“A”)
StringBuilder buf = { 0,0,0,0,}
^
Thread t2 buf.append(“B”)
Thread t1 buf.append("A")
StringBuffer buf = { 0,0,0,0,}
^
Thread t2 buf.append("B")
StringBuilder 不是同步的
append();
2 Vector 和 Hashtable 是同步的
ArrayList 和 HashMap 不是同步的
3 Collections.synchronizedList()
Collections.synchronizedMap()
ArrayList list = new ArrayList();
List syncList = Collections.synchronizedList(list);
5.10Timer(定时器)使用(java.util.Timer)
六 网络编程
6.1 IP协议
每个设备在网络中的唯一标识
每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个 地址。
ipconfig:查看本机IP192.168.12.42
ping:测试连接192.168.40.62
本地回路地址:127.0.0.1 255.255.255.255是广播地址
IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年 初已经用尽。
IPv6:8组,每组4个16进制数。
1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f
1a2b::aaaa:0000:0000:0000:aabb:1f2f
1a2b:0000:aaaa::aabb:1f2f
1a2b:0000:aaaa::0000:aabb:1f2f
1a2b:0000:aaaa:0000::aabb:1f2f
6.2端口号
每个程序在设备上的唯一标识
每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。
端口号范围从0-65535
编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
常用端口:
mysql: 3306
oracle: 1521
web: 80
tomcat: 8080
QQ: 4000
feiQ: 2425
6.3协议
UDP
面向无连接,数据不安全,速度快。不区分客户端与服务端。(类似你发短信,不管号码是否存在,也不管对方是否可以接收到,反正你发了就号)
TCP
面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据(类似你打电话给女神,必须等到女神接听才可以去表白)
HTTP协议是基于TCP协议的
6.4 Socket编程 TCP 协议编程
6.5. TCP 服务端编程(食堂)(java.io.,java.net.,java.lang.*)
创建ServerSocket实例绑定一个服务端口(Socket/套接字 端口号)
开始ServerSocket实例 的监听, 等待客户端的连接
如果有客户连接进来, 就获得了客户的套接字(Socket)实例
客户的套接字(Socket)实例中包括与客户端建立的连接流
为这个客户(Socket) 创建一个服务线程, 提供服务(run方法)
继续等待下一个连接,返回到2)
服务线程 完成通讯服务过程
端口号: 0~65535, 1K以下留给系统使用
6.6 TCP 客户端编程
6.7服务器端步骤:
(1)建立一个服务器Socket(ServerSocket)指定端口并开始监听
(2)使用accept()方法等待客户端触发通信
(3)打开输入输出流
(4)获取客户端信息,即从输入流读取信息
(5)给客户端一个响应,即向输出流写入信息
(6)关闭资源
6.8客户端步骤:
(1)建立客户端Socket连接,指定服务器的位置IP以及端口
(2)打开输入输出流
(3)发送客户端登录信息,即向输出流写入信息
(4)接收服务器段的响应,即从输入流读取信息
(5)关闭资源