Java基础 线程 通信

来源:互联网 发布:淘宝官方自营店是什么 编辑:程序博客网 时间:2024/06/05 04:19

进程>线程

单进程单线程:一个人在一个桌子上吃菜。
单进程多线程:多个人在同一个桌子上一起吃菜。
多进程单线程:多个人每个人在自己的桌子上吃菜。
多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。
在 Windows 中,进程创建的开销不容忽视。换句话说就是,Windows 编程中不建议你创建进程,如果你的程序架构需要大量创建进程,那么最好是切换到 Linux 系统。

如果你是写服务器端应用的,其实在现在的网络服务模型下,开桌子的开销是可以忽略不计的,因为现在一般流行的是按照 CPU 核心数量开进程或者线程,开完之后在数量上一直保持,进程与线程内部使用协程或者异步通信来处理多个并发连接,因而开进程与开线程的开销可以忽略了。


进程
进程是程序的一次动态执行过程,占用特定的地址空间;
每个进程是独立的,由三部分组成 CPU data code

线程
称为轻量级进程
一个进程可以拥有多个并行的线程
一个进程中的线程是共享相同的内存单元/内存地址空间--->可以访问相同的变量和对象,而且他们从同一堆中分配对象-->通信,数据交换,同步操作
因为在同一地址空间上进行的所以他们之间信息传递更快


线程的概念及使用
线程
在一个程序中同时运行的多个独立流程,每一个独立的流程就是一个线程
线程并发
一个程序中,多个线程并发执行
主线程
当JVM启动之后,加载类文件,发现main方法,那么就会为main方法创建一个线程,
用于main方法执行,这个为main方法创建的线程称为主线程
Java中实现自定义线程类的方法
继承java.lang.Thread类
实现java.lang.Runnable接口
继承Thread类
自定义一个线程类继承自Thread
重写Thread的run方法
创建自定义线程类对象
开启线程:调用自定义线程类对象的start方法
实现Runnable接口 (静态代理 设计模式)
自定义一个线程类实现Runnable接口
重写Thread的run方法
创建自定义线程类对象,并传入Thread对象中
开启线程:调用自定义线程类对象的start方法
好处
1,避免单继承的局限性
2,便于共享资源
callable接口 创建繁琐 但是有返回值 可以声明异常
扣儿A波
线程的5个状态sleep
新建状态new对象的时候
可运行状态在进程名.start的时候
阻塞状态在sleep休眠 wait等待 join插入
运行状态执行run方法的时候
死亡状态运行完以后 kill 等时候

阻塞状态
Thread的void sleep(long millis)方法用于使当前线程休眠指定的毫秒数
sleep方法对线程的控制是非常不精确的
join方法可以精确控制线程,也会导致线程阻塞join特点:如果当前线程中调用了另外一个线程的join方法,当前线程会立即阻塞,直到另外一个线程运行完成
join阻塞的问题
相互等对方完成

线程同步synchronized
被多线程并发访问时如果一个对象有可能出现数据不一致的问题,那么这个对象称为线程不安全的对象
synchronized同步代码块
格式:
synchronized(对象){
同步的代码
}
同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。

同步方法
在函数上加上synchronized修饰符即可。
[修饰符] synchronized 返回值类型 方法名(参数列表){ }
synchronized(this)
{
包含方法中需要被锁住的代码块
}
线程通信wait、notify
线程死锁
线程死锁解决wait和notify
线程通信
数据紊乱

数据紊乱同步代码块

数据紊乱解决方案1


--------------------线程通信----------------------
package duoxiancheng;

public class BeiCeShi
{ //这是余额的变量
int m;
//这是标识符 用来判断是在存钱还是取钱 当为false就存钱 true就取钱
boolean flag=false;
//一个有参构造器
public BeiCeShi(int i)
{
super();
this.m = i;
}
//使用wait notifyAll 需要加同步锁
public synchronized void add(int i) throws InterruptedException
{ //判断是不是true 是的话就进入等待
if (flag)
{ //调用这个方法的需要等到
this.wait();
}else {
m+=i;
System.out.println(Thread.currentThread().getName()+i);
//改变标识符
flag=true;
//唤醒所有调用这个方法的线程
this.notifyAll();
}
}
public synchronized void jian(int i) throws InterruptedException
{ //判断这个标识符不为flash时进去
if (!flag)
{ //等待
this.wait();
}else {
m-=i;
System.out.println(Thread.currentThread().getName()+i);
//改变标识符
flag=false;
//唤醒所有线程
this.notifyAll();
}
}
}



网络相关概念

计算机网络
把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,
从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源
计算机网络的主要功能
资源共享
信息传输与集中处理
均衡负荷与分布处理
综合信息服务 (www/综合业务数字网络 ISDN)
网络中的基本概念
IP地址:用于唯一识别连接到Internet上的计算机
地址表示方式
IPv4: 点分10进制表示方式,四个整数用点分开,每个十进制数字代表一个8 bits整数,如192.168.123.1
IPv6: 点分16进制表示方式,八个整数用点分开,每个十六进制数字代表一个16bits整数,如CDCD:910A:2222:5498:8475:1111:3900:2020
域名,如www.sina.com.cn
本地IP,如127.0.0.1或者localhost
端口号0-65535之间 2字节
0—1023是公认端口号,即已经公认定义或者为将来公认定义的软件预留
1024-65535没有被公共定义的端口号,用户可以自己定义端口号的用途
URL:统一资源定位符
uri:统一资源
4部分组成http协议 默认是这个协议
域名
文件名和端口 默认80
资源文件
网络模型

网络协议 (TCP/IP)
网络通信协议
计算机网络中实现通信必须有一些约定即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准
TCP协议(transmission control protocol)
TCP/IP协议是一个面向连接的、可靠的协议
TCP/IP是专门设计用于在不可靠的因特网上提供可靠的、端到端的字节流通信的协议.它是一种面向连接的协议。TCP连接是字节流而非报文流。
UDP协议(user datagram protocol)
UDP协议是一个不可靠的、无连接协议
UDP向应用程序提供了一种发送封装的原始IP数据报的方法、并且发送时无需建立连接.是一种不可靠的连接。

网络编程C/S存在局域网 B/S互联网
TCP/IP编程
java.ner.Socket
java.ner.ServerSocket


服务器

客户端

UDP编程
客户端
1类 DatagramSocket DatagramPacket
2 准备数据 字节数据
3打包DatagramPacket +发送的地址和端口
4发送
5释放资源
服务端
1创建 服务端DatagramSocket +指定端口
2准备接受容器 字节数组 封装DatagramPacket
3包接受数据
4 分析
5 释放资源
服务器
客户端

TCP通信

服务端----------------------package seven;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;//建立一个服务器端public class MySeven{public static void main(String[] args) throws IOException, InterruptedException{//创建一个服务端 开一个8800端口ServerSocket ss=new ServerSocket(8000);//给一个提示System.out.println("--------服务器已经启动端口8800-------");//等待客户端的链接ss.accept 会返回一个客户端对象Socket ck = ss.accept();//给个提示System.out.println("---客户端连接成功---");//获取客户端的输入流InputStream is=ck.getInputStream();//获取客户端的输出流OutputStream os=ck.getOutputStream();//设置一个读取长度的byte数组byte[] bytes=new byte[1024];//将内容读取到byte数组中is.read(bytes);//将数组中的内容转换出来System.out.println(new String(bytes));String str="我要断开连接了!";//将内容发送出去 需要转换成byte数组os.write(str.getBytes());//关闭两个流is.close();os.close();}}客户端------------------------package seven;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.net.UnknownHostException;//创建一个客户端测试public class MyClient{public static void main(String[] args) throws UnknownHostException, IOException{//创建一个客户端 需要填写服务器的地址和服务器开放的端口Socket ck=new Socket("192.168.10.50",8000);//获取输入流InputStream is=ck.getInputStream();//获取输出流OutputStream os=  ck.getOutputStream();//发送内容给服务器os.write("我是客户端".getBytes());//读取服务器的内容byte[] byets=new byte[1024];//读取服务器内容is.read(byets);System.out.println(new String(byets));//关闭ck.close();}}


UDP通信

服务端package udpseven;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;/** 创建一个UDP服务器 * */public class UDPSeven{public static void main(String[] args){try{//创建一个UDP服务端DatagramSocketDatagramSocket ds=new DatagramSocket(8000);System.out.println("服务区创建成功,等待链接");//创建一个需要读取的长度byte[] bytes=new byte[1024];//创建一个接受对象DatagramPacketDatagramPacket dp=new DatagramPacket(bytes, bytes.length);//接受数据ds.receive(dp);//发送数据ds.send(dp);//打印内容System.out.println(new String(bytes));//关闭ds.close();} catch (SocketException e){e.printStackTrace();}catch (IOException e) {}}}========================================客户端package udpseven;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetSocketAddress;import java.net.SocketException;/** *创建一个客户端测试 */public class UDPClient{public static void main(String[] args){try{//创建一个客户端对象DatagramSocket ds=new DatagramSocket();//接受数据的存放位置和长度byte[] bytes="我是客户端".getBytes();//创建一个需要接受数据的对象即目标地址DatagramPacket dp=new DatagramPacket(bytes, bytes.length,new InetSocketAddress("127.0.0.1", 8000));//发送数据ds.send(dp);//创建一个接受数据的容器和定义一次接受的长度byte[] byte1=new byte[1024];//创建一个接受数据的对象DatagramPacket dp1=new DatagramPacket(byte1, byte1.length);//接受服务器转发的数据ds.receive(dp1);//打印System.out.println(new String(byte1));//关闭ds.close();} catch (SocketException e){e.printStackTrace();}catch (IOException e) {}}}





原创粉丝点击