1.线程通信
线程间通信一个前提条件就是线程同步
同步代码块
同步方法
2.notify
可以唤醒因wait方法进入阻塞的线程
notifyAll可以唤醒因wait方法进入阻塞的所有线程
例1:张三李四共同card,实现存一笔取一笔
同步代码块
public class Test {
public static void main(String[] args) {
Card card = new Card();
Zs zs = new Zs(card);
Ls ls = new Ls(card);
Thread t = new Thread(zs);
Thread t2 = new Thread(ls);
t.start();
t2.start();
}
}
class Card{
int money = 0;
}
class Zs implements Runnable{
Card card;
public Zs(Card card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (card) {
if(card.money>=10000) {
//等待
try {
card.wait();
} catch (Exception e) {
// TODO: handle exception
}
}
card.money+=10000;
System.out.println("张三存了10000,还剩"+card.money);
//唤醒
card.notify();//将阻塞状态中线程唤醒
}
}
}
}
class Ls implements Runnable{
Card card;
public Ls(Card card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (card) {
//等待
if(card.money<=0) {
try {
card.wait();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//李四可以取钱
card.money-=10000;
System.out.println("李四取了10000还剩"+card.money);
card.notifyAll();
}
}
}
}
同步方法
public class Test2 {
public static void main(String[] args) {
Card2 card = new Card2();
Zs2 zs2 = new Zs2(card);
Ls2 ls2 = new Ls2(card);
Thread t = new Thread(zs2);
Thread t2 = new Thread(ls2);
t.start();
t2.start();
}
}
class Card2 extends Object{
int money = 0;
public synchronized void save() {
if(this.money>=10000) {
//等待
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception
}
}
money+=10000;
System.out.println("张三存了10000,还剩"+money);
//唤醒
this.notify();//将阻塞状态中线程唤醒
}
public synchronized void take() {
if(this.money<=0) {
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//李四可以取钱
money-=10000;
System.out.println("李四取了10000还剩"+money);
this.notifyAll();
}
}
class Zs2 implements Runnable{
Card2 card;
public Zs2(Card2 card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
card.save();
}
}
}
class Ls2 implements Runnable{
Card2 card;
public Ls2(Card2 card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
card.take();
}
}
}
例2.两个线程实现12A34B56C78D…5152Z
public class Test3 {
public static void main(String[] args) {
Resource resource = new Resource();
PrintLetter printLetter = new PrintLetter(resource);
PrintNum printNum = new PrintNum(resource);
Thread t = new Thread(printLetter);
Thread t2 = new Thread(printNum);
t.start();
t2.start();
}
}
class Resource{
boolean flag = true;//打印了字母,该打数字了
//false打印了数字,该打字母了
public synchronized void printLetter(int num) {
if(flag==true) {//打印了字母,该打数字了,让字母等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print((char)num);
//打印完字母后改变flag的状态
//打印完字母该打数字
flag = true;
this.notify();
}
public synchronized void printNum(int num) {
if(flag==false) {//打印了数字,该打字母了,让数字等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(num+""+(num+1));
flag = false;
this.notify();
}
}
class PrintLetter implements Runnable{
Resource resource;
public PrintLetter(Resource resource) {
super();
this.resource = resource;
}
@Override
public void run() {
for (int i = 0; i < 26; i++) {
resource.printLetter(65+i);;
}
}
}
class PrintNum implements Runnable{
Resource resource;
public PrintNum(Resource resource) {
super();
this.resource = resource;
}
@Override
public void run() {
for (int i = 1; i < 52; i+=2) {
resource.printNum(i);
}
}
}
3.condition代替监视器方法
如果想要实现线程通信,前提必须线程同步
Lock lock unlock
Condition await() signal() signalAll()
如果想要通过Lock锁的这种方式来实现线程通信
- Lock锁对象 唯一
- 给每一个线程创建一个监视器
- Condition zs = lock.newCondition();
- 每个监视器只负责一个线程, 负责给线程进行await signal
注意:不要弄混线程监视器
例:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test2 {
public static void main(String[] args) {
Card card = new Card();
Zs zs = new Zs(card);
Ls ls = new Ls(card);
Thread t = new Thread(zs);
Thread t2 = new Thread(ls);
t.start();
t2.start();
}
}
class Card extends Object{
int money = 0;
//1.要进行同步
//Lock
Lock lock = new ReentrantLock();
//2.线程通信,需要监视器
Condition zs = lock.newCondition();
Condition ls = lock.newCondition();
public void save() {
lock.lock();
if(money>=10000) {
try {
zs.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
money+=10000;
System.out.println("张三存了10000,还剩"+money);
ls.signal();
lock.unlock();
}
public void take() {
lock.lock();
if(money<=0) {
try {
ls.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
money-=10000;
System.out.println("李四取了10000还剩"+money);
zs.signal();
lock.unlock();
}
}
class Zs implements Runnable{
Card card;
public Zs(Card card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i <10; i++) {
card.save();
}
}
}
class Ls implements Runnable{
Card card;
public Ls(Card card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
card.take();
}
}
}
4.消费者生产者模型
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Test {
public static void main(String[] args) {
Market market = new Market();
Product product = new Product(market);
Custom custom = new Custom(market);
Thread t = new Thread(product);
Thread t2 = new Thread(custom);
t.start();
t2.start();
}
}
//面包类
class Bread{
String brand;
int id;
public Bread(String brand, int id) {
super();
this.brand = brand;
this.id = id;
}
@Override
public String toString() {
return "Bread [brand=" + brand + ", id=" + id + "]";
}
}
class Market{
Set<Bread> set = new HashSet<>();
public synchronized void product(Bread bread) {
if(set.size()>=10) {
try {
this.wait();//让生产者等着
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//生产
set.add(bread);//生产了
System.out.println("生产者生产了一个面包"+bread);
this.notify();//唤醒消费者
}
public synchronized void sale() {
//没有库存了,不能消费了
if(set.size()<=0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//还有面包,还可以继续消费
Iterator<Bread> iterator = set.iterator();
while (iterator.hasNext()) {
Bread bread = iterator.next();
System.out.println("消费者消费了一个面包"+bread);
iterator.remove();
break;
}
this.notify();
}
}
class Product implements Runnable{
Market market;
public Product(Market market) {
super();
this.market = market;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Bread bread = new Bread("达利园", i);
market.product(bread);
}
}
}
class Custom implements Runnable{
Market market;
public Custom(Market market) {
super();
this.market = market;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
market.sale();
}
}
}
5.yield ,sleep , wait 区别
是否释放cpu 进入到就绪的条件 其他线程抢占情况
yield 会释放cpu 立马进入就绪状态 同级或优先级更高的先执行
sleep 自己进入到阻塞状态,并且释放cpu,但是不会释放锁 睡醒了就进入就绪状态 所有线程都可以抢
wait 自己进入到阻塞状态,会释放cpu,也会释放锁 必须通过notify唤醒才会进入到就绪状态 所有线程都可以抢
6.网络编程基础
在同一个网络中不同机器之间的通信。
按照地理范围:广域网( Internet) ,城域网( 一个城市、多个城市,长城宽带),局域网(机房)
网络参考模型
OSI参考模型:包括七层:[物理层]、[数据链路层]、[网络层]、[传输层]、[会话层]、[表示层]和[应用层]
通信协议
通信协议分类:
互联网IP协议:IPV4和IPV6,互联网协议
传输层协议:TCP和UDP
应用层协议:HTTP HTTPS安全性更高
TCP协议:TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的基于字节流的传输层通信协议。数据大小无限制。建立连接的过程三次握手、四次断开。
三次握手的过程,为了数据安全,能够让对方一定接听到,面向连接
UDP协议:UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是TCP/IP参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小64Kb。
UDP不需要进行连接,速度会更快,数据不可靠,数据大小不能超过64kb
IP协议:[Internet Protocol]网际协议,能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。IP协议中包含一块非常重要的内容就是为计算机分配了一个唯一标识即IP地址。
IP地址是数字型的,是一个32位的整数,通常将其分成4个8位的二进制数,每8位之间用圆点隔开, 每个8位整数可以转换为一个0~255的十进制整数,分为IPV4和IPV6
查看ip:ipconfig
IP地址分类
A类:保留给政府结构,1.0.0.1 ~ 126.255.255.254
B类:分配给中型企业,128.0.0.1 ~ 191.255.255.254
C类:分配给任何需要的个人,192.0.0.1 ~ 223.255.255.254
D类:用于组播,224.0.0.1 ~ 239.255.255.254
E类:用于实验,240.0.0.1 ~ 255.255.255.254
回环地址:127.0.0.1,指本机,一般用于测试使用,使用ping命令测试: ping 127.0.0.1
端口
数据的发送和接收都需要通过端口出入计算机,端口号用于唯一标识通信实体上进行网络通讯的程序,同一台机器上不能两个程序占用同一个端口
取值范围:0~65535
查看端口占用: netstat -ano
端口分类:
公认端口:0~1023
注册端口:1024~49151
动态或私有端口:49152~65535
常用端口:
mysql:3306
oracle:1521
tomcat:8080
web服务器(http):80
ftp服务器:21
SMTP 25
POP3 110
7.InetAddress类常用方法
查看本地主机,地址,名字,查看其它主机
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Test {
public static void main(String[] args) {
try {
//得到本地主机
InetAddress localhost = InetAddress.getLocalHost();
System.out.println(localhost);
//得到本地主机名字
String hostname = localhost.getHostName();
System.out.println(hostname);
//得到本地主机地址
String hostAddress = localhost.getHostAddress();
System.out.println(hostAddress);
//得到其他主机名字
InetAddress byName = InetAddress.getByName("www.baidu.com");
System.out.println(byName);
//得到其他主机名字
InetAddress name = InetAddress.getByName("10.10.12.225");
System.out.println(name);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
8.Socket通信模型
客户端发送消息,服务端接收消息
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
//发送信息
String str = "老师下课啦";
//0~65535 0~1023 1024~49151
Socket socket = new Socket("127.0.0.1",6666);
//找出OutputStream
OutputStream os = socket.getOutputStream();
os.write(str.getBytes());
os.flush();
//关闭
os.close();
socket.close();
}
}
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
//服务端Socket
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服务端启动");
//接收
Socket socket = serverSocket.accept();
//从接收到的客户端的对象中将数据取出来
InputStream is = socket.getInputStream();
byte[] bs = new byte[20];
int num = is.read(bs);
String str = new String(bs,0,num);
System.out.println("接收到客户端发过来的信息"+str);
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}