多线程
线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
进程
进程是程序的基本执行实体
1.什么是多线程?
有了多线程,我们就可以让程序同时做多件事情
2.多线程的作用?
提高效率
3.多线程的应用场景?
只要你想让多个事情同时运行就需要用到多线程
比如:软件中的耗时操作、所有的聊天软件、所有的服务器
1.并发:在同一时刻,有多个指令在单个CPU交替执行
2.并行:在同一时刻,有多个指令在多个CPU上同时执行
多线程的三种实现方式
1.继承Thread类
代码样例:
public class Mythread extends Thread{
@Override
public void run() {
//书写线程要执行的代码
for(int i=1;i<=100;i++){
System.out.println(getName()+"你好");
}
}
}
/*-----------------------------------------------------------*/
public class DXC_thread {
public static void main(String[] args) {
Mythread mt1=new Mythread();
Mythread mt2=new Mythread();
mt1.setName("线程1");
mt2.setName("线程2");
mt1.start();
mt2.start();
}
}
2.实现Runnable接口类
代码样例:
//第一个类
public class MyRun implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Thread t=Thread.currentThread();
System.out.println(t.getName()+"你好"+i);
}
}
}
/*------------------------------------------------------*/
//第二个类
public class DXC_Rannable {
public static void main(String[] args) {
//创建MyRun对象
//表示多线程的任务
MyRun mr=new MyRun();
//创建线程对象
Thread t1=new Thread(mr);
Thread t2=new Thread(mr);
//给线程设置名字
t1.setName("线程1");
t2.setName("线程2");
//设置优先级 越大越先执行的概率大
t1.setPriority(1);
t2.setPriority(10);
//开启线程
t1.start();
t2.start();
}
}
3.实现Callable接口类
//第一个类
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum=0;
for(int i=1;i<=100;i++)
sum+=i;
return sum;
}
}
/*-----------------------------------------------------*/
//第二个类
public class DXC_Callable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建MyCallable的对象
MyCallable mc=new MyCallable();
//创建FutureTask的对象(作用管理多线程运行的结果)
FutureTask<Integer> ft=new FutureTask<>(mc);
//创建线程的对象
Thread t1=new Thread(ft);
//启动线程
t1.start();
//获取多线程运行结果
Integer ans=ft.get();
System.out.println(ans);
}
}
常用的成员方法
守护线程
当一个线程执行结束后,该线程也会结束
实际应用:当你用qq给别人发送文件,中途退出这个聊天界面,文件发送也停止
代码样例:
//第一个类
public class DXC_lr {
public static void main(String[] args) {
lr_Mythread1 mt1=new lr_Mythread1();
lr_Mythread2 mt2=new lr_Mythread2();
mt1.setName("女神");
mt2.setName("备胎");
//Mt2设置为守护线程
mt2.setDaemon(true);
mt1.start();
mt2.start();
}
}
/*----------------------------------------------------*/
//第二个类
public class lr_Mythread1 extends Thread{
@Override
public void run() {
//书写线程要执行的代码
for(int i=1;i<=10;i++){
System.out.println(getName()+"你好"+i);
}
}
}
/*----------------------------------------------------*/
//第三个类
public class lr_Mythread2 extends Thread{
@Override
public void run() {
//书写线程要执行的代码
for(int i=1;i<=100;i++){
System.out.println(getName()+"你好"+i);
}
}
}
同步代码块
把操作共享数据的代码锁起来
特点1:锁默认打开,有一个线程进去了,锁自动关闭
特点2:里面的代码全部执行完毕,线程出来,锁自动打开
代码样例:
//第一个类
public class DXC_aq {
public static void main(String[] args) {
aq_Mythread1 mt1=new aq_Mythread1();
aq_Mythread1 mt2=new aq_Mythread1();
aq_Mythread1 mt3=new aq_Mythread1();
mt1.setName("窗口1");
mt2.setName("窗口2");
mt3.setName("窗口3");
mt1.start();
mt2.start();
mt3.start();
}
}
/*--------------------------------------------------*/
//第二个类
public class aq_Mythread1 extends Thread{
static int ticket=0;
//static Object obj=new Object();
@Override
public void run() {
while(true){
//同步代码块
synchronized (aq_Mythread1.class) {
if (ticket < 100) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket++;
System.out.println(getName()+"正在卖第" + ticket + "票!!!");
} else {
break;
}
}
}
}
}
等待唤醒机制
等待唤醒机制是一个十分经典的多线程协作的模式
样例
代码实现示范:
//第一个类
public class sc_And_xf {
public static void main(String[] args) {
//创建线程对象
cook ck=new cook();
Foodie fd=new Foodie();
ck.setName("厨师");
fd.setName("吃货");
ck.start();
fd.start();
}
}
/*------------------------------------------------------------------*/
//第二个类
public class Desk {
//锁对象
public static Object lock=new Object();
//总个数
public static int count=10;
//0表示没有面条,1表示有面条
public static int flag=0;
}
/*------------------------------------------------------------------*/
//第三个类
public class cook extends Thread{
@Override
public void run() {
while(true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
//判断桌子上是否有食物
if(Desk.flag==1){
try {
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else{//如果没有制作食物
System.out.println("厨师做了一碗面条!!");
//修改桌子上的食物状态
Desk.flag=1;
//提醒消费者吃
Desk.lock.notifyAll();
}
}
}
}
}
}
/*------------------------------------------------------------------*/
第四个类
public class Foodie extends Thread{
@Override
public void run() {
while(true) {
synchronized (Desk.lock) {
if (Desk.count == 0)
break;
else {
//如果没有,就等待
if(Desk.flag==0){
try {
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
//如果有,就开吃
else {
//吃的总数减少1
Desk.count--;
System.out.println("吃货正在吃面条,还能再吃"+Desk.count+"碗!!");
Desk.flag=0;
//唤醒厨师继续做
Desk.lock.notifyAll();
}
}
}
}
}
}
阻塞队列实现等待唤醒机制
代码示范样例:
//第一个类
public class DXC_zs {
public static void main(String[] args) {
//1.创建阻塞队列的对象
ArrayBlockingQueue<String>queue=new ArrayBlockingQueue<>(1);
//2.创建线程的对象,并把阻塞队列传递过去
cook1 c=new cook1(queue);
Foodie1 f=new Foodie1(queue);
//3.开启线程
c.start();
f.start();
}
}
/*-----------------------------------------------------------------------*/
//第二个类
public class cook1 extends Thread{
ArrayBlockingQueue<String>queue;
public cook1(ArrayBlockingQueue<String>queue){
this.queue=queue;
}
@Override
public void run() {
while(true){
try {
queue.put("面条");
System.out.println("厨师做了一碗面条");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
/*-----------------------------------------------------------------------*/
//第三个类
public class Foodie1 extends Thread{
ArrayBlockingQueue<String> queue;
public Foodie1(ArrayBlockingQueue<String>queue){
this.queue=queue;
}
@Override
public void run() {
while(true) {
while(true){
try {
String food = queue.take();
System.out.println("吃货吃了"+food);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
线程的状态
网络编程
BS架构和CS架构
BS与CS架构的优缺点
BS优点
不需要开发客户端,只需要开发服务端
用户不需要下载,打开浏览器就能使用
BS缺点
如果应用过大,用户体验受到影响
CS优点
画面可以做的非常精美,用户体验好
需要开发客户端,也需要开发服务端
CS缺点
用户需要下载和更新的时候太麻烦
网络编程三要素
1.IP
IP:设备在网络中的地址,是唯一的标识(理解为上网设备在网络中的地址,是唯一的)
常见的IP分类
IPv4,IPv6
IPv6
全称:Internet Protocolversion6,互联网通信协议第六版。
由于互联网的蓬勃发展,IP地址的需求量愈来愈大,而IPv4的模式下IP的总数是有限的。
采用128位地址长度,分成8组。
1.lp的作用
设备在网络中的地址,是唯一的标识
2.IPV4有什么特点
目前的主流方案
最多只有2^32次方个ip,
目前已经用完了
3.IPv6有什么特点
为了解决IPv4不够用而出现的
最多有2^128次方个ip
可以为地球上的每一粒沙子都设定ip
特殊IP地址
127.0.0.1,也可以是localhost:是回送地址也称本地回环地址,也称本机IP,永远只会寻找当前所在本机。
建议:自己练习就写127.0.0.1
常用的CMD命令
ipconfig:查看本机IP地址
ping:检查网络是否连通
2.端口号
应用程序在设备中唯一的标识。
端口号:由两个字节表示的整数,取值范围:0~65535
其中0~1023之间的端口号用于一些知名的网络服务或者应用
我们自己使用1024以上的端口号就可以了。
注意:一个端口号只能被一个应用程序使用。
3.协议
数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp。
UDP协议
不管是否已经连接成功
用户数据报协议(User Datagram Protocol)
UDP是面向无连接通信协议。
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
UDP通信程序步骤
发送数据
1.创建发送端的Datagramsocket对象
2.数据打包(DatagramPacket)
3.发送数据
4.释放资源
接收数据
1.创建接收端的Datagramsocket对象
2.接收打包好的数据
3.解析数据包
4.释放资源
发送数据代码样例:
package test12;
import java.io.IOException;
import java.net.*;
public class UDP_out {
//1.创建Datagramsocket对象(快递公司)
//细节:
//绑定端口,以后我们就是通过这个端口往外发送
//空参:所有可用的端口中随机一个进行使用
//有参:指定端口号进行绑定
public static void main(String[] args) throws IOException {
DatagramSocket ds=new DatagramSocket();
//2.打包数据
String str ="你好威啊!!!";
byte[] bytes =str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
//3.发送数据
ds.send(dp);
//4.释放资源
ds.close();
}
}
接收数据代码样例:
package test12;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDP_in {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象(快递公司)
//细节:
//在接收的时候,一定要绑定端口
//而且绑定的端口一定要跟发送的端口保持一致
DatagramSocket ds=new DatagramSocket(10086);
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
//3.解析数据包
byte[] data = dp.getData();
int len = dp.getLength();
//是从哪台电脑上来的
InetAddress address =dp.getAddress();
//是从哪个端口发送过来的
int port = dp.getPort();
System.out.println("按收到数据"+ new String(data,0,len));
System.out.println("该数据是从"+ address +"这台电脑中的"+ port +"这个端口发出的");
//4.释放资源
ds.close();
}
}
两边运行后结果
TCP协议
传输控制协议TCP(Transmission ControlProtocol)
TCP协议是面向连接的通信协议。
速度慢,没有大小限制,数据安全,
确保连接成功
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象
通信之前要保证连接已经建立
通过Socket产生IO流来进行网络通信
TCP通信步骤
发送数据代码样例:
package test12;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class TCP_out {
public static void main(String[] args) throws IOException {
//TCP协议,发送数据
//1.创建Socket对象
//如果连不上会报错
Socket socket =new Socket("127.0.0.1",10000);
//2.从连接通道中获取输出流
OutputStream os=socket.getOutputStream();
os.write("你好".getBytes());
//3.释放资源
os.close();
socket.close();
}
}
接收数据代码样例:
package test12;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TCP_in {
public static void main(String[] args) throws IOException {
//TCP接收协议
//1.创建对象ServerSocket
ServerSocket ss=new ServerSocket(10000);
//2.监听客户端的连接
Socket socket= ss.accept();//死等
//3.从连接通道中获取输入流读取数据
InputStream is = socket.getInputStream();
//利用转换流转换为字符流,防止乱码
InputStreamReader isr=new InputStreamReader(is);
int len;
//byte [] bytes=new byte[1024];
while((len=isr.read())!=-1){
//System.out.println(new String(bytes,0,len));
System.out.print((char)len);
}
}
}
两边运行后结果