24/04/15总结

多线程:

线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位
并发:在同一时刻,有多个指令在单个cpu上交替执行
并行:在同一时刻,有多个指令在多个cpu上同时执行
多线程的实现方式
1.继承Thread类的方式进行实现
2.实现Runnable接口的方式进行实现
3.利用Callable接口和Future接口方式实现

 

Thread
第一步自己定义一个类继承Thread
第二步重写run方法
第三步创建子类的对象,并启动线程
 //创建子类的对象
        Demo2myThread t1 = new Demo2myThread();
        Demo2myThread t2 = new Demo2myThread();
        t1.setName("线程1");          //setName在Thread类里
        t2.setName("线程2");
        //开启线程
        t1.start();
        t2.start();
        //可以看到线程1和线程2是交互执行的
public class Demo2myThread extends Thread{
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"HelloWorld");     //getName在Thread类中

        }
    }
}
Runnable
第一步先自己定义一个类实现Runnable接口
第二步重写里面的Runnable方法
第三步创建自己的类的对象
第四步创建一个Thread类的对象,并开启线程
package com.itheima.demo15多线程;

public class Demo3 {
    public static void main(String[] args) {
        //Runnable
        //第一步先自己定义一个类实现Runnable接口
        //第二步重写里面的Runnable方法
        //第三步创建自己的类的对象
        //第四步创建一个Thread类的对象,并开启线程

        //创建Demo3MyRun的对象
        //表示多线程要执行的任务
        Demo3MyRun mr = new Demo3MyRun();
        //创建线程对象
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);
        t1.setName("线程1");
        t2.setName("线程2");
        //开启线程
        t1.start();
        t2.start();
    }
}
public class Demo3MyRun implements Runnable{
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            //先获取到当前线程的对象
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+"HelloWorld");       //因为getName是Thread里的所以这里不能直接用
        }
    }
}
利用Callable接口和Future接口方式实现
特点:可以获取到多线程运行的结果
第一步:创建一个类MyCallable实现Callable接口
第二步:重写call(是有返回值的,表示多线程运行的结果)
第三步:创建MyCallable的对象(表示多线程要执行的任务)
第四步:创建FutureTask(因为Future是接口)的对象(作用管理多线程运行的结果)
第五步:创建Thread类的对象,并启动(表示线程)
   //创建MyCallable的对象
        Demo4MyCallable mc = new Demo4MyCallable();
        //创建FutureTask的对象
        FutureTask<Integer> ft = new FutureTask<>(mc);
        //创建线程的对象
        Thread t1 = new Thread(ft);
        //启动线程
        t1.start();
        //获取多线程运行的结果
        Integer result = ft.get();
        System.out.println(result);
package com.itheima.demo15多线程;

import java.util.concurrent.Callable;

public class Demo4MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        //求1-100之间的和
        int sum=0;
        for (int i = 1; i <= 100; i++) {
            sum+=i;
        }
        return sum ;
    }
}
Thread中常见的成员方法
方法名称                                              说明
String getName()                                  返回此线程的名称
void setName(String name)                         设置线程的名字(构造方法也可以设置名字)
static Thread currentThread()                     获取当前线程的对象
static void sleep(long time)                      让线程休眠指定的时间,单位为毫秒
setPriority(int newPriority)                      设置线程的优先级(最小1,最大10,默认5,越大优先级越高)
final int getPriority()                           获取线程的优先级
final void setDaemon(boolean on)                  设置为守护线程
public static void yield()                        出让线程/礼让线程
public static void join()                         插入线程/插队线程
void setName(String name)
细节:如果我们没有给线程设置名字,线程也是有默认的名字的:Thread-x(x起始为0)
static Thread currentThread()
细节:
获取当前线程的对象
当Java虚拟机启动之后,会自动的启动多条线程
其中有一条线程就叫做main线程
他的作用就是去调用main方法,并执行里面的代码
在以前,我们写的所有的代码,其实都是运行在main线程当中
static void sleep(long time)
细节:
1、哪条线程执行到这个方法,那么哪条线程就会在这里停留对应的时间
2、方法的参数:就表示睡眠的时间,单位毫秒
3、当时间到了之后,线程会自动的醒来,继续执行下面的其他代码
setPriority(int newPriority)
final int getPriority()
t1.setPriority(1);    //设置优先级为1
t2.setPriority(10);   //设置优先级为10
System.out.println(t1.setPriority());     //输出t1的优先级
final void setDaemon(boolean on)
细节:
当其他的非守护线程执行完毕之后,守护线程会陆续结束(不是立马结束)
通俗易懂:
当非守护线程结束了,那么守护线程也没有存在的必要了
t2.setDaemon(true);           //开启守护线程
public static void yield()
在重写的run方法里:Thread.yield();    //表示出让当前cpu的执行权(尽可能会让结果均匀一些,不是绝对的)
就是当前线程弄完之后就会出让cpu的执行权
public static void join()
t1.join();    //表示把t1这个线程,插入到当前线程之前
线程安全的问题
需求:
某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票
买票引发的安全问题:
  //相同的票出现了多次
  //出现了超出范围的票
解决方法:同步代码锁(把操作共享数据的代码锁起来)
格式:
synchronized (锁){     (注意:锁对象一定要唯一:就是前面加个static)
操作共享数据的代码
}
特点1:锁默认打开,有一个线程进去了,锁自动关闭
特点2:里面的代码全部执行完毕,线程出来,锁自动打开
 //创建线程对象
        Demo7myThread t1 = new Demo7myThread();
        Demo7myThread t2 = new Demo7myThread();
        Demo7myThread t3 = new Demo7myThread();
        //起名字
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        //开启线程
        t1.start();
        t2.start();
        t3.start();
package com.itheima.demo15多线程;

public class Demo7myThread extends Thread{
    static  int ticket =0;
    @Override
    public void run() {
        while (true) {
           synchronized (Demo7myThread.class){              //细节1:synchronized要放在循环里面
               if(ticket<100) {                             //细节2:一般用类名.class用作锁的对象(当前字节码文件对象),(锁对象一定要唯一)
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   ticket++;
                   System.out.println(getName() +"正在卖"+ ticket+"张票");
               }
               else {
                   break;
               }
           }
        }

    }
}
//同步方法:就是把synchronized关键字加到方法上
    //格式:修饰符 synchronized 返回值类型 方法名(方法参数) {...}
    //特点1:同步方法是锁住方法里面所有的代码
    //特点2:锁对象不能自己指定(非静态: this,静态:当前类的字节码文件对象)
   static  int ticket=0;
    @Override
    public void run() {
        //1.循环
        while(true){
            //2.(同步方法)
                if (method()) break;
        }
    }

    private synchronized boolean method() {         //此时方法是非静态的,它的锁对象是this
        if(ticket==100)
            return true;
        else {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticket++;
            System.out.println(Thread.currentThread()+"正在卖"+ ticket+"张票");
        }
        return false;
    }

 

线程池
线程池只要核心原理:
1.创建一个池子,池子中是空的
2.提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子
下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可
3.但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待
线程池代码实现
Executors:线程池的工具类通过调用方法返回不同类型的线程池对象
                      方法名称                                                                                             说明
public static ExecutorService newCachedThreadPool()                               创建一个没有上限的线程池(上限是int类型的最大值)
public static ExecutorService newFixedThreadPool(int nThreads)                    创建有上限的线程池
 

网络编程: 
 

网络编程:在网络通信协议下,不同计算机上运行的程序,进行的数据传输。
不管是什么场景,都是计算机跟计算机之间通过网络进行数据传输,数据传输就需要网络编程
C/S:客户端/服务器
B/S:浏览器/服务器
BS架构的优缺点
不需要开发客户端,只需要页面+服务端
用户不需要下载,打开浏览器就能使用
如果应用过大,用户体验受到影响
CS架构的优缺点
画面可以做的非常精美,用户体验好
需要开发客户端,也需要开发服务端
//static InetAddress getByName(string host)      确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
        //String getHostName()                          获取此IP地址的主机名
        //String getHostAddress()                       返回文本显示中的IP地址字符串

 

        //1.获取InetAddress的对象
        //IP的对象
        InetAddress address = InetAddress.getByName("snow");
        System.out.println(address);

        String name = address.getHostName();//获取电脑的主机名
        System.out.println(name);
        String ip = address.getHostAddress();//获取电脑的IP
        System.out.println(ip);
端口号
应用程序在设备中唯一的标识。
端口号:由两个字节表示的整数,取值范围:0~65535
其中0~1023之间的端口号用于一些知名的网络服务或者应用
我们自己使用1024以上的端口号就可以了
注意:一个端口号只能被一个应用程序使用
UDP协议
用户数据报协议(User Datagram Protocol)
UDP是面向无连接通信协议。
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
TCP协议
传输控制协议TCP(Transmission control Protocol
TCP协议是面向连接的通信协议。
速度慢,没有大小限制,数据安全

 


        //1.创建DatagramSocket对象(快递公司)
        //细节:
        //绑定端口:以后我们就是通过这个端口往外发送
        //空参:所有可用的端口中随机一个进行使用
        //有参:指定端口号进行绑定
        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();
 //UDP通信程序(接收数据)
        //1.创建DatagramSocket对象(快递公司)
        //细节:
        //在接收的时候,一定要绑定端口
        //而且绑定的端口一定要跟发送的端口保持一致
        DatagramSocket ds2 = new DatagramSocket(10086);

        //2.接收数据包
        byte[] bytes2 = new byte[1024];
        DatagramPacket dp2 = new DatagramPacket(bytes2,bytes2.length);       //(接收放到的地方,接收放到的地方的长度)
        //该方法是阻塞的
        //程序执行到这一步的时候,会在这里死等
        //等发送端发送消息
        ds2.receive(dp2);

        //3.解析数据包
        byte[] data = dp2.getData();     //获取数据
        int len = dp2.getLength();       //获取多少个字节数据
        InetAddress address1 = dp2.getAddress();         //获取从哪台电脑发来的
        int port1 = dp2.getPort();           //获取从哪个端口发来的

        System.out.println("接收到数据"+ new String(data,0,len));
        System.out.println("该数据是从"+ address1 +"这台电脑中的"+ port1 +"这个端口发出的");

        //4.释放资源
        ds2.close();
单播:以前的代码就是单播
组播:组播驰址:224.0.0.0~239.255.255.255
其中224.0.0.0~224.0.0.255 为预留的组播地址
广播:255.255.255.255
 //1.创建MulticastSocket对象
        MulticastSocket ms = new MulticastSocket();     //组播创建这个

        //2.打包数据
        String str = "你好";
        byte[] bytes = str.getBytes();//只能发字节数据
        InetAddress address = InetAddress.getByName("224.0.0.2");
        int port=10086;
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
        //(要发的数据,数据的长度,往哪台电脑发,发到哪个端口上)

        //3.发送数据
        ms.send(dp);

        //4.释放资源
        ms.close();

 

  //1.创建 MulticastSocket对象
        MulticastSocket ms = new MulticastSocket(10086);

        //2.将当前本机,添加到224.0.0.1的这一组当中
        InetAddress address = InetAddress.getByName("224.0.0.2");
        ms.joinGroup(address);
        //3.接收数据包
        byte[] bytes2 = new byte[1024];
        DatagramPacket dp2 = new DatagramPacket(bytes2,bytes2.length);       //(接收放到的地方,接收放到的地方的长度)
        //该方法是阻塞的
        //程序执行到这一步的时候,会在这里死等
        //等发送端发送消息

        ms.receive(dp2);

        //4.解析数据包
        byte[] data = dp2.getData();     //获取数据
        int len = dp2.getLength();       //获取多少个字节数据
        InetAddress address1 = dp2.getAddress();         //获取从哪台电脑发来的
        int port1 = dp2.getPort();           //获取从哪个端口发来的

        System.out.println("接收到数据"+ new String(data,0,len));
        System.out.println("该数据是从"+ address1 +"这台电脑中的"+ port1 +"这个端口发出的");

        //5.释放资源
        ms.close();
TCP通信程序
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象
通信之前要保证连接已经建立
通过Socket产生IO流来进行网络通信
客户端(Socket)---输出流---->   通信之前要保证连接已经建立      ----输入流---->服务器端(SeverSocket)
客户端:
创建客户端的Socket对象(Socket)与指定服务端连接
Socket(string host, int port)         (服务器的ip,端口号)
获取输出流,写数据
OutputStream getOutputStream()
释放资源
void close()
服务器端:
创建服务器端的Socket对象(ServerSocket)
ServerSocket(int port)    (此时服务器绑定的端口要和客户端绑定的端口保持一致)
监听客户端连接,返回一个Socket对象
Socket accept()
获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream()
释放资源
void close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值