Java多多积累之线程池、网络编程、内部类完整讲解

线程安全问题

线程安全,必然会带来性能的降低,线程安全,适合多线程访问。
线程不安全,相对于线程安全性能较高,线程不安全,适合单线程访问。

线程池

1、池的本质,就是一种“缓存”技术,是否要缓存一个对象,取决于该对象的创建成本,但是使用缓存技术也要考虑系统内存大小;缓存的本质就是牺牲空间换取时间,线程对象的成本较大,所以在适当的时候选择使用线程池。
2、使用线程池的原因:多线程运行时间,系统不断的启动和关闭新线程,成本非常高,会过渡消耗系统资源,以及过渡切换线程的危险,从而导致系统资源的崩溃,这时,线程池就是最好的选择。
3、线程池的概念:线程池就是预先在内存中创建好一些线程,它们的集合称为线程池,使用线程池可以很好的提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一个线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为一个空闲状态,等待执行下一个任务。
4、线程池的工作机制:在线程池的编程模式下,任务是提交给整个线程池,而不是直接提交给某个线程,线程池在拿到任务后,就在内部寻找是否有空闲的线程,如果有,则将任务交给这个空闲的线程;一个线程同时只能执行一个任务,但是可以同时向一个线程池提交多个任务。

package com.wlx.day12;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolDemo
{
    public void  threadpool()throws Exception
    {
        //创建线程池对象
        ExecutorService threadpool = Executors.newCachedThreadPool();
        //使用线程池中的线程
        threadpool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"---");
            }
        });
        //使用线程完成以后,让其空闲1000毫秒
        Thread.sleep(1000);
        //再次使用线程池
        threadpool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"***");
            }
        });
        //使用shutdown()关闭线程池
        threadpool.shutdown();
    }

    public static void main(String[] args)throws Exception
    {
        new ThreadPoolDemo().threadpool();
    }

}

ThreadLocal

ThreadLocal采用了“以空间换时间”的方式,每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个变量,这样就避免了多个线程对共享数据/共享资源的操作发生错误的问题。

package com.wlx.day12;

/**
 * 使用多线程完成飞机购票,某订票系统还剩5张票,现有3个人去买票,
 * 在买票时,会出现系统延迟的情况,请使用程序实现3人购票的情况。
 */
public class Ticket implements Runnable
{
    //定义一个变量用于缓存剩余的5张票
    private Integer p = 5;

    //创建ThreadLocal对象
    private static  final  ThreadLocal<Integer>  local = new ThreadLocal<>();

    @Override
    public   void run()
    {
        for (int i = 0; i < 10; i++)
        {
            buyTicket();
        }
    }

    /**
     * 获取ThreadLocal中的对象
     * @return
     */
    public Integer getTicket()
    {
        if(local.get() == null)
        {
            local.set(p);
        }

        return  local.get();
    }

    /**
     * 买票的方法
     */
    private void buyTicket() {

        //获取ThreadLocal中的票数
        Integer count = getTicket();
        if(count > 0)
        {
            try {
                System.out.println("系统延迟中...");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"---买票"+(count--));
            local.set(count);
        }
    }


    public static void main(String[] args)
    {
        Ticket  t = new Ticket();
        //创建3个线程代表3个人
        Thread  tom = new Thread(t,"tom");
        Thread  jim = new Thread(t,"jim");
        Thread  lilei = new Thread(t,"lilei");
        //3个人去买票
        tom.start();
        jim.start();
        lilei.start();
    }
}

volatile

volatile解决脏读(可见性),不会重排序,但是不能保证原子性,如果要保证原子性还是需要使用加锁,或使用ThreadLocal。

网络编程

端口号取值范围:0~65535,建议使用9999以上的端口号。

TCP编程

TCP编程,在发送和接收数据时,必须等待服务端启动后,才可以进行链接,然后才可以进行信息发送,发生数据时,不会出现丢失数据报包的情况。

服务端

package com.wlx.day12;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务器端
 */
public class Server
{
    public static void main(String[] args)throws Exception
    {
        //创建服务器端对象
        ServerSocket  serverSocket = new ServerSocket(10002);
        System.out.println("等待客户端链接...");
        while (true)
        {
            //等待客户端链接
            Socket s =  serverSocket.accept();
            //创建字节输入流对象
            InputStream inputStream = s.getInputStream();
            //创建DataInputStream对象
            DataInputStream  dis = new DataInputStream(inputStream);
            System.out.println("IP:"+s.getInetAddress()+"\t 说:"+dis.readUTF());
        }
    }
}

客户端

package com.wlx.day12;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 客户端
 */
public class Client
{
    public static void main(String[] args)throws Exception
    {
        //创建客户端对象
        Socket  s = new Socket("192.168.219.1",10001);
        //创建字节输出流对象
        OutputStream  os =  s.getOutputStream();
        //创建DataOutputStream对象
        DataOutputStream dos = new DataOutputStream(os);
        //向服务端发送信息
        dos.writeUTF("hello server");

    }
}

图形化界面

package com.wlx.day12;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;

public class FrameServer
{
    public static void main(String[] args)
    {
        //创建图形化界面的顶层窗口对象
        JFrame  jf = new JFrame("聊天窗口");
        //创建聊天窗口的文本域窗口对象
        JTextArea  jta = new JTextArea();
        //创建滚动条对象,并将jta添加进来
        JScrollPane  jsp = new JScrollPane(jta);
        //创建一个JPanel对象
        JPanel  jp = new JPanel();
        //创建文本框对象
        JTextField  jtf = new JTextField(20);
        //创建按钮对象
        JButton  jButton = new JButton("发送");
        jp.add(jtf);
        jp.add(jButton);
        //将jsp以及文本域添加到顶层窗口中,默认添加到中间位置
        jf.add(jsp);
        //添加到jf的最下面
        jf.add(jp,BorderLayout.SOUTH);
        //设置窗口大小
        jf.setSize(600,300);
        //设置显示位置
        jf.setLocation(300,300);
        //设置窗口可见
        jf.setVisible(true);
        //禁止最大化
        jf.setResizable(false);
        //设置窗口关闭按钮可以进行关闭
        jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        String ip = "192.168.219.1";
        int port = 10002;
        //添加文本框监听处理
        jtf.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    //创建客户端对象
                    Socket  s = new Socket(ip,port);
                    //创建字节输出流对象
                    OutputStream os =  s.getOutputStream();
                    //创建DataOutputStream对象
                    DataOutputStream dos = new DataOutputStream(os);
                    String msg = jtf.getText();
                    jtf.setText("");
                    //向服务端发送信息
                    dos.writeUTF(msg);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });

        //为按钮添加监听
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    //创建客户端对象
                    Socket  s = new Socket(ip,port);
                    //创建字节输出流对象
                    OutputStream os =  s.getOutputStream();
                    //创建DataOutputStream对象
                    DataOutputStream dos = new DataOutputStream(os);
                    String msg = jtf.getText();
                    jtf.setText("");
                    //向服务端发送信息
                    dos.writeUTF(msg);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });

        try {
            //创建服务器端对象
            ServerSocket serverSocket = new ServerSocket(port);
            jta.append("服务器已启动,等待客户端链接...");
            jta.append("\n");
            while (true)
            {
                //等待客户端链接
                Socket s =  serverSocket.accept();
                //创建字节输入流对象
                InputStream inputStream = s.getInputStream();
                //创建DataInputStream对象
                DataInputStream dis = new DataInputStream(inputStream);
                jta.append(LocalDateTime.now()+" :"+s.getInetAddress()+" 说:"+dis.readUTF()+"\n");
                jta.append("\n");
            }
        } catch (IOException e) {
            System.out.println("出现异常了...");
        }
    }
}

UDP编程

UDP编程,在发送和接收数据时,不用等待链接后再发送,可以直接发送,数据报包丢失对于UDP是正常现象。

卖家

发送数据。

package com.wlx.day12;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * UDP卖家
 */
public class Seller
{

    public static void main(String[] args)throws Exception
    {
        DatagramSocket  ds = new DatagramSocket(10003);
        byte[]  b = "hello".getBytes();
        InetAddress ia = InetAddress.getLocalHost();
        System.out.println(ia);
        //10004是买家的端口号
        DatagramPacket  dp = new DatagramPacket(b,b.length,ia,10004);
        ds.send(dp);
        System.out.println("包裹已发出");

    }

}

买家

接收数据

package com.wlx.day12;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * UDP买家
 */
public class Buyer
{
    public static void main(String[] args)throws Exception
    {
        DatagramSocket  ds = new DatagramSocket(10004);
        byte[] b = new byte[1024];
        DatagramPacket dp = new DatagramPacket(b,b.length);
        ds.receive(dp);
        String s = new String(b);
        System.out.println("接收到的包裹是:"+s);
    }
}

内部类(了解)

定义:
定义在类的内部的类就是内部类,即定义在一个类的类体中或一个方法中的类就是内部类。
实例内部类
静态内部类
局部内部类
匿名内部类

1.1、实例内部类

定义:
没有被static静态修饰的,直接定义在类体中的一个类就是实例内部类。
实例内部类的实例对象是在所在类的实例基础上进行创建的。
实例内部类中的实例方法,调用外部类中的实例成员可以通过如果下格式调用:
外部类名.this.实例成员
实例内部类中也可以编写静态成员。
实例内部类中的静态成员使用和外部类类似,不能在静态成员中使用this关键字。

1.2、静态内部类

定义:
被static静态修饰的,直接定义在类体中的一个类就是静态内部类。
静态内部类中在使用外部类的成员时,和前面一样,只有一点,不能直接在静态内部类中使用外部类的this关键字。

1.3、匿名内部类

格式:
new 子类或实现类()
{
子类类体/实现类类体
};
备注:
子类用的是父类的类名。
实现类用的是接口的类名。
备注:
匿名内部类中,除了不能写构造方法,其他都可以写,但是还是要使用多态的方式访问匿名内部类中的方法,由于属性没有多态,匿名内部类中的属性只能在匿名内部类中使用。

package com.wlx.day12;

/**
 * 外部类
 */
public class ClassDemo
{

    String username = "jim";
    static int  uage = 678;
    String usersex = "man";
    static int userage = 89;




    /**
     * 定义一个实例内部类
     */
    public  class  InnerClass
    {
        private static String username = "tom";
        private  int userage = 123;

        public InnerClass()
        {
            System.out.println("InnerClass---");
        }

        public static void  staticMethod()
        {
            ClassDemo cd = new ClassDemo();
            System.out.println("staticMethod---");
            System.out.println("uage---"+uage);
            System.out.println("usersex ---"+cd.usersex);
            System.out.println("cd.username ---"+cd.username);

        }

        public void  noStaticMethod()
        {
            System.out.println("no  Static  Method ");
            System.out.println("uage---"+uage);
            System.out.println("usersex ---"+usersex);
            System.out.println("ClassDemo.this.username ---"+ClassDemo.this.username);
            System.out.println("ClassDemo.userage---"+ClassDemo.userage);
        }

    }


    public  void  outMethod()
    {
        //创建内部类对象
        InnerClass  ic = new InnerClass();
        System.out.println(ic.userage);
        ic.noStaticMethod();
        //System.out.println(InnerClass.username);
        InnerClass.staticMethod();
    }

    public  static class StaticInnerClass
    {
        private static String username2 = "tom";
        private  int userage2 = 123;

        public StaticInnerClass()
        {
            System.out.println("InnerClass---");
        }

        public static void  staticMethod2()
        {
            ClassDemo cd = new ClassDemo();
            System.out.println("staticMethod---");
            System.out.println("uage---"+uage);
            System.out.println("usersex ---"+cd.usersex);
            System.out.println("cd.username ---"+cd.username);

        }

        public void  noStaticMethod2(String username2)
        {
            ClassDemo cd = new ClassDemo();
            System.out.println("no  Static  Method ");
            System.out.println("uage---"+uage);
            System.out.println("usersex ---"+cd.usersex);
            System.out.println("cd.username ---"+cd.username);
            System.out.println("ClassDemo.userage---"+ClassDemo.userage);
            System.out.println(this.userage2);
        }
    }

    public  void  outMethod2()
    {
        StaticInnerClass sic = new StaticInnerClass();
        System.out.println(sic.userage2);
        sic.noStaticMethod2("");
        //System.out.println(InnerClass.username);
        StaticInnerClass.staticMethod2();
    }


    public  void  hello(int a)
    {
        //定义局部变量,默认情况下,局部变量在被局部内部类使用时,被final修饰
        String  str = "jbbl";
        int abc = a;

         class HelloWorld
        {
            private static String username = "tom";
            private  int userage = 123;

            public HelloWorld()
            {
                System.out.println("InnerClass---");
            }

            public static void  staticMethod()
            {
                ClassDemo cd = new ClassDemo();
                System.out.println("staticMethod---");
                System.out.println("uage---"+uage);
                System.out.println("usersex ---"+cd.usersex);
                System.out.println("cd.username ---"+cd.username);

            }

            public void  noStaticMethod()
            {
                System.out.println("no  Static  Method ");
                System.out.println("uage---"+uage);
                System.out.println("usersex ---"+usersex);
                System.out.println("ClassDemo.this.username ---"+ClassDemo.this.username);
                System.out.println("ClassDemo.userage---"+ClassDemo.userage);
                System.out.println(str);
                System.out.println(abc);
                System.out.println(a);
            }

        }

        HelloWorld helloWorld = new HelloWorld();

    }


    public static void main(String[] args) {

        //创建实例内部类对象
//        InnerClass  innerClass = new ClassDemo().new InnerClass();
        //等价于
        ClassDemo  cd = new ClassDemo();
        //创建实例内部类对象
        InnerClass  innerClass = cd.new InnerClass();


        cd.outMethod();

        //创建匿名内部类
       InterfaceDemo id = new InterfaceDemo(){

           static int userage = 123;
           static String username = "tom";

           static
           {
               System.out.println("static----");
           }

            {
                System.out.println("8888");
            }

          public void abstractorMethod()
          {

          }

          public static  void hello()
          {

          }

          public  void  world()
          {

          }
        };


        System.out.println(InterfaceDemo.userage);

    }


}

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值